list comprehensions で ネストしたい
for for をしたいなと思った。
data = [[ 3 ], [4] ] [ e for row in data for e in row ]
ネストと if 文
data = [[ 3 ], [4] ] [ e for row in data for e in row if e %2 ==0 ]
楽しい。 filter も map も要らない。list comprehensions 便利。
for for をしたいなと思った。
data = [[ 3 ], [4] ] [ e for row in data for e in row ]
data = [[ 3 ], [4] ] [ e for row in data for e in row if e %2 ==0 ]
楽しい。 filter も map も要らない。list comprehensions 便利。
レポジトリはこちら
python3.6 でフォーマット文字列が導入されたので、ようやくPythonをシェルコマンド呼び出しに使って使いやすくなったので、ガンガン書き直した。
python3.6 で書き直した。
pyenv を使う
git clone https://github.com/pyenv/pyenv echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile ./pyenv/shims/bin/pyenv rehash pyenv install 3.6.2 pyenv global 3.6.2 pyenv rehash hash -r
pyenv の準備ができたら
python play_radiko.py abc
ABC*1 を再生
ストリーミングを保存、タイムフリーの取得、再生、再生しながら保存などもついでにヤッておいた
rtmpdump は ffmpeg だけでもできるし、mplayer と ffmpeg 使ってるし、相当に冗長なんだけど、とりあえずraspi で 動けばいい的な
Radikoの再生&録音スクリプトをPythonで書きなおした - それマグで!
http://takuya-1st.hatenablog.jp/entry/2014/09/28/051532
オーディオジャックから、ラジオを垂れ流したい。散々やってきたけど、Raspi ZeroからRaspi3に変えたので、オーディオジャックが使えるようになった
rtmpdump は必要。
rtmpdump -v -r rtmpe://f-radiko.smartstream.ne.jp\ --app ABC/_definst_\ --playpath simul-stream.stream\ -W http://radiko.jp/apps/js/flash/myplayer-release.swf\ -C S:"" -C S:"" -C S:"" -C S:${authtoken}\ --live --stop 5400 \ | omxplayer -o local --hw --timeout 30s --no-keys pipe:0
omxplayer が rtmp には対応してるけどキーを送れないのと、rtmpe は出来ないっぽい。この辺はそのうちもう少し調べたい。もしキー送信できたら omxplayer だけで完結するので。
--hw
つけたら、ハードウェアデコードしてくれるらしいが、、効果あるんだろうか
omxplayer に pipe でデータを渡すには --no-keys
をつけて pipe:0
を指定する
この辺は過去資料にある。→ raspberry pi の omxplayer を標準入力でパイプして使う。 - それマグで!
コレだけの設定で、結構楽ちんに野球中継を垂れ流す事ができて幸せな感じある。
ffmpeg を使うしか無い。omxplayer で m3u8 は再生できるが、CookieとUA以外の、HTTPヘッダを追加できないみたいなので。
ffmpeg -y \ -headers 'X-Radiko-AuthToken: ${authtoken}'\ -i 'https://radiko.jp/v2/api/ts/playlist.m3u8?station_id=${channel}&ft=${start}&to=${end}'\ -loglevel panic -acodec copy - \ | omxplayer -o local --timeout 30s --no-keys pipe:0
タイムフリー楽しい。
Raspberry Pi にスピーカー繋いで、ラジオを流せればとっても楽ちんだと思いません?
2017-09から、らじる★らじるが m3u8 に変更になっているので HLS のm3u8 を指定するだけなのでとても簡単
omxplayer --timeout 60s -o local https://nhkradiobkr1-i.akamaihd.net/hls/live/512291/1-r1/1-r1-01.m3u8
たったこれだけ。
timeout がデフォルトの10s だとakamai の仕様で接続が切れるらしいので、 --timeout
で長めに設定する必要がある。
-o
は アウトプットを オーディオジャックに指定している。raspi は alsa とか設定するより omxplayer を使うのが一番ラクですよね。
心配なら --audio_queue
を付けても良いかもしれない
omxplayer が rtmpe と ヘッダ追加 に対応してくれたらradikoもrtmpdump 無しでいけるのになぁ。
takuya@raspberrypi:~ $ cat /etc/debian_version 8.0
takuya@raspberrypi:~ $ cat /etc/os-release PRETTY_NAME="Raspbian GNU/Linux 8 (jessie)" NAME="Raspbian GNU/Linux" VERSION_ID="8" VERSION="8 (jessie)" ID=raspbian ID_LIKE=debian HOME_URL="http://www.raspbian.org/" SUPPORT_URL="http://www.raspbian.org/RaspbianForums" BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs" takuya@raspberrypi:~ $
これで、バージョン番号と名前が確認できます。
他にもいろいろありますが。この方法が手軽だと思う。
今回は raspberry pi の raspbian で確認しました。
記述を追加
方法は、通常の debian アップグレードと同じでいいですね。
できるだけ最新版にしておく。
sudo apt-get update && sudo apt-get upgrade -y
grep jessie /etc/apt/ -R
Debianのアップグレードと同じように、/etc/apt でバージョン名を指定する
sudo sed -i 's/jessie/stretch/g' /etc/apt/sources.list sudo sed -i 's/jessie/stretch/g' /etc/apt/sources.list.d/raspi.list
自動更新してたので念の為にコレも。
sudo sed -i 's/jessie/stretch/g' /etc/apt/apt.conf.d/50unattended-upgrades
takuya@raspberrypi:~ $ sudo grep jessie /etc/apt/ -R takuya@raspberrypi:~ $
コレだけが置換された。
takuya@raspberrypi:~ $ sudo grep stretch /etc/apt/ -R /etc/apt/apt.conf.d/50unattended-upgrades:// n,codename (eg, "stretch", "stretch-updates") /etc/apt/apt.conf.d/50unattended-upgrades:// ${distro_codename} Installed codename (eg, "stretch") /etc/apt/apt.conf.d/50unattended-upgrades:// "o=Raspbian,n=stretch"; /etc/apt/sources.list:deb http://mirrordirector.raspbian.org/raspbian/ stretch main contrib non-free rpi /etc/apt/sources.list:#deb-src http://archive.raspbian.org/raspbian/ stretch main contrib non-free rpi /etc/apt/sources.list.d/raspi.list:deb http://archive.raspberrypi.org/debian/ stretch main ui /etc/apt/sources.list.d/raspi.list:#deb-src http://archive.raspberrypi.org/debian/ stretch main ui
sudo apt update
更新が終われば、アップグレードしたいけど・・・
もし心配なら、シミュレーターでシミュレーションする。
apt --simulate upgrade apt --simulate dist-upgrade
パッケージを余りたくさん入れてなかったり、httpdサーバーの設定を変えてなかったり、smb.conf とかサーバの設定を変えてなければ、ほとんどなにも起きないのでシミュレーターは必要ないと思う。
sudo apt dist-upgrade
takuya@raspberrypi:~ $ cat /etc/debian_version 9.0
絶対、車輪の再発明になるので検索させていただきました。
kill コマンドとppid をきっちり使いこなせば、ちゃんと理解できるんだろうけど、それを説明するのはかったるいので、再帰呼出しがイメージしやすいのではなかろうか。
#!/usr/bin/env bash killtree() { local parent=$1 child for child in $(ps -o ppid= -o pid= | awk "\$1==$parent {print \$2}"); do killtree $child done kill $parent } killtree $@
https://stackoverflow.com/questions/392022/best-way-to-kill-all-child-processes
chrome ってキーチェイン使わないとおもってたら、キーチェインのダイアログを聞いてきたのであたらためて調べてみた
Chromeはキーチェインを「読み込み専用」で使うようです。
の OR 条件になっているようです。
書込みは、内蔵パスワード保存のみのようです。 更新もないようです。
いったん、Safari起動して保存してからChromeで開くと良いようですね。
あきらかに、ChromeがKeychainsに新規項目追加したと思うんだけど。なんで新規項目追加されたのかちょっとつい調査したい。
PC/MacのDNSキャッシュを消しても、なんかダメだなと思ったら、どうやらChromeのDNSキャッシュがあるようで。
DNS触ってnginx を切り替えてるときに、chrome の dns cache はうざい。
chrome のDNSキャッシュは chrome-urls からアクセスできる。 → chrome://net-internals/#dns
chrome://net-internals/#dns
ほんとうはDNSのキャッシュ設定を変えれば良いんだろうけど。キャッシュ消すのが一番早い
DNS浸透待ちはしないでね。浸透言うな警察が来るよ。cacheにも注意しよう
cache で検索しても出てこないのでキーワードを見直し
コマンドを組み立てた文字列を配列で渡すなら、split が便利だけど、shlex.split ならさらに安全に渡せるらしい。
self.prcs = Popen( shlex.split(cmd), shell=False )
たしかに文字列をsplit すると暴走するものね。
また shlex.quote もあるのでこちらも便利そう
Shell経由させないほうが孫プロセスを作らなくて楽なイメージ有る。
mariaDB に変えたので、PAMによる認証連携は、最初から付属してます。便利!
mysql の管理者(root) で ログインしてプラグインを有効化する
INSTALL SONAME 'auth_pam';
これでほとんど完了。あー楽。
mysql にユーザーを追加する。
CREATE USER takuya identified via pam
これでいい。楽ちん。
ここは何もしなくて良さそう。auth を使うみたい。以前に mysql + pam であれこれ設定してるので、パーミッションとかは省略して動いた。
もし、mysql やmariadb といった名前でPAMに書きたい場合(たとえば www-data や apache や postgresql などと共通名にしたいとか)
ユーザーできたので、プラグインがPAMに認証を丸投げできるように、PAM側で受け取れるように設定する。
CREATE USER takuya identified via pam USING 'my-pam-name' #
以前はこっちをやってた。
同じことを homebrew の brew コマンドでやるにはどうすればいいか
brew outdated
これで、新しくなってる brew のパッケージの一覧が取得できる。
https://stackoverflow.com/questions/12946505/how-can-i-tell-which-homebrew-formulae-are-upgradable
探したら、policykit-1 というパッケージに含まれてた。
http://manpages.ubuntu.com/manpages/xenial/man1/pkexec.1.html
pkexec の pk は policy kit の略なんですね
ubuntu の LTS Serverには含まれてなかったんですよね。。。便利だから使ってるけど余り一般的ではないコマンドなのなか。本来なら pkexec の代わりには何を使うべきなんだろう。
sudo だと環境変数の設定を sudoers に書く必要とかあるし、gksudo だと面倒だし一覧楽な do as だと思うんだけどな。
nginx の プロキシの upstream を unix ドメインソケットに設定したのだけれど動かないのね。 だから、ソケットが正しく動いてるかテストしてみたかったの。
nc -U unix:/path/to/some.sock
コレを使えばコマンドからunixソケットにアクセスして、アクセス可能かテストできるし、パーミッションもここでテストできる。
echo ' GET / ' | nc -U /path/to/unicorn.sock
これで応答するか調べられる。
pkexec でnc 実行して別ユーザからの読込とアクセスを見てみたら確認できた
echo "GET /" | sudo pkexec --user www-data nc -U /var/opt/gitlab/gitlab-workhorse/socket nc: unix connect failed: Permission denied
これで、 www-data ( nginx ) から gitlab のソケットにアクセスできてないことが分かる。
アクセス出来ないときはパーミッションをいじるよりもグループをいじったほうが確実だね。
usermod -aG gitlab-wwwdata www-data
これで試してみる
echo "GET /" | sudo pkexec --user www-data nc -U /var/opt/gitlab/gitlab-workhorse/socket HTTP/1.1 400 Bad Request Content-Type: text/plain; charset=utf-8 Connection: close
400 Bad request が正しく返ってくるので通信できることがわかった。これでnginx の設定が間違ってないことが確認できて安心。
traditional な nc ( netcat ) は -U オプションが存在しないので、invalid オプションになる。
/bin/nc.openbsd
nc: invalid option -- 'U' nc -h for help
BSDパッケージのnetcat をインストールする必要があった。
apt install netcat-openbsd
zip ファイルをアップロードしたり、バックアップしたりしてて、「ファイルが壊れた」のを検出したりしたかった。状況を再現したいなと思ってもそう簡単に壊れたりはしないので、壊れたファイルを作る必要がああった。
dd
壊れたファイルを作るには、ファイルに0バイトを書き込んで壊したり、半分にちぎったり、変なバイトを書き込む。
これをやるには cp などのコマンドでは出来ないので、 dd コマンド
を使うことになる。Cやpythonやruby でfopenして書いても良いんだけど、dd コマンドが一番楽だと思う。
最初に dd でファイルをコピーして、使い方を確認しておく
takuya@Desktop$ dd if=test.zip of=test.safe.zip 0+1 records in 0+1 records out 438 bytes copied, 0.000324 s, 1.4 MB/s takuya@Desktop$ md5sum test*.zip 48949110457174e7f10541080235174b test.safe.zip 48949110457174e7f10541080235174b test.zip
先頭から400バイトを読み込んで、残りをコピーぜずに、中断された状況を作ってみる。
takuya@Desktop$ dd if=test.zip of=test.corrupted.zip bs=1 count=400 400+0 records in 400+0 records out 400 bytes copied, 0.00151 s, 265 kB/s
結果を確認
takuya@Desktop$ md5sum test*.zip 7eeef77e910c3a770c557e3bb9d3d8a1 test.corrupted.zip 48949110457174e7f10541080235174b test.zip
壊れたことを確認する。 unzip しようとしても、return code = 9 が帰ってきて、異常終了したことが分かる。
takuya@Desktop$ unzip -t test.corrupted.zip ; echo $? Archive: test.corrupted.zip End-of-central-directory signature not found. Either this file is not a zipfile, or it constitutes one disk of a multi-part archive. In the latter case the central directory and zipfile comment will be found on the last disk(s) of this archive. unzip: cannot find zipfile directory in one of test.corrupted.zip or test.corrupted.zip.zip, and cannot find test.corrupted.zip.ZIP, period. 9
ただしこの状態でも zip のエントリ一覧は取れたりする・・・だから壊れたことを再現できるよね。
takuya@Desktop$ lsar test.corrupted.zip ; echo $? test.corrupted.zip: Zip tet/ tet/a tet/b 0
最初に、変なバイトを書き込むファイルを用意する。
takuya@Desktop$ cp test.zip test.wrong-byte.zip
400 バイト目から、30バイトのZEROを書き込んで壊す。
takuya@Desktop$ dd if=/dev/zero of=test.wrong-byte.zip bs=1 skip=400 count=30 30+0 records in 30+0 records out 30 bytes copied, 0.000153 s, 196 kB/s
ファイルが壊れたことを確認してみる
takuya@Desktop$ unzip test.wrong-byte.zip -t Archive: test.wrong-byte.zip End-of-central-directory signature not found. Either this file is not a zipfile, or it constitutes one disk of a multi-part archive. In the latter case the central directory and zipfile comment will be found on the last disk(s) of this archive. unzip: cannot find zipfile directory in one of test.wrong-byte.zip or test.wrong-byte.zip.zip, and cannot find test.wrong-byte.zip.ZIP, period.
これで、ファイルが壊れたりHDDが壊れて、ファイルが正しく転送できなかったとかプログラマ(わたし)がアホで、ファイルの転送時のネットワーク・エラー処理が甘く変なファイルが作っちゃったとか事件を再現してソレに対応した回復プログラムを作れる実験出来ると思った。