sh・bash・zsh等, shellの違いでハマりやすい部分とか
前提として
sh
の実体は環境によって POSIX互換bash (bash --posix)
であったり, dash
であったり, busybox
であったりと様々である (ls -l `which sh`
とすれば実体がわかる). 唯一の制約は POSIX互換であること だ (※どこぞの今はなきお行儀が悪いOSを除けば). そのためシバンで sh
を利用する場合は, 最低限のPOSIX互換shell上で動作するように書かれるべき で, 例えば bash
拡張を用いる時はシバンで bash
を指定するべきだ. しかしながら, シバンで sh
を指定しているにも関わらずPOSIXの範囲を超えた命令を利用しても動いてしまうケースもままあり, 意識しないと難しい.
ハマりやすい差異の一例
空白 (正確には区切り文字) が含まれた変数
変数の展開され方が異なる
# bash, bash --posix, dash, busybox : > 'a b' x='a b' mv $x c # error (`mv a b c` と解釈される) ls # -> 'a b'
# zsh : > 'a b' x='a b' mv $x c # (`mv 'a b' c` と解釈される) ls # -> c
文字列の比較
==
による文字列比較はPOSIX互換のものではない
# dash [ 'a' = 'a' ] && echo 'ok' || echo 'ng' # -> ok [ 'a' == 'a' ] && echo 'ok' || echo 'ng' # error -> ng
# zsh [ 'a' = 'a' ] && echo 'ok' || echo 'ng' # -> ok [ 'a' == 'a' ] && echo 'ok' || echo 'ng' # error
# bash, bash --posix, busybox [ 'a' = 'a' ] && echo 'ok' || echo 'ng' # -> ok [ 'a' == 'a' ] && echo 'ok' || echo 'ng' # -> ok
プロセスリダイレクト
これは bash
・zsh
固有の機能の一つ
# bash --posix, dash, busybox cat <(echo 'a') # error
# bash, zsh cat <(echo 'a') # -> a
結論
shellは方言や実装で微妙に違うところが多すぎて厳しい
Docker Composeでビルド時に任意のイメージ名を指定する方法
公式リファレンスを見ても分かりづらいのでメモ.
Docker Compose経由でビルドされたデフォルトイメージ名は {プロジェクト名}_{サービス名}
となる (デフォルトプロジェクト名はディレクトリ名だが, コマンドラインオプション -p
から指定可能). 例えば以下のような構成であれば, イメージ名が hoge_fuga
, コンテナ名が piyo
となる.
hoge ┣ Dockerfile ┣ docker-compose.yml ┗ ...
# docker-compose.yml version: '2' services: fuga: build: . container_name: piyo
しばしば長ったらしいイメージ名になってしまう. そこで以下のように image
を追加することでイメージ名を指定できる. image
と build
が同時に宣言されている場合は, ビルドが優先的に実行されて, image
はその構成に使われる (image
によるプルは発生しない).
結果としてイメージ名が nyan
, コンテナ名が piyo
となる. ちなみにタグの付与も image
からできる. これらは全て, Compose File v2からの機能である.
# docker-compose.yml version: '2' services: fuga: build: . image: nyan container_name: piyo
既存環境に手を加えずにサクッとHTTPS化する (NAT配下でもok)
MP4をストリームで扱う場合の落とし穴
MP4コンテナの仕様上, ストリームとして読み込ませるとうまく扱えない.
cat video.mp4 | ffmpeg -i pipe:0 ...
といった形で扱うと Error while decoding stream #0:1: Invalid data found when processing input
として怒られてしまう. 素直に別コンテナを使うか, ファイルとして扱う (ffmpeg -i video.mp4 ...
) 必要があるようだ. -analyzeduration
や -probesize
も試したが, ストリームの場合は意味がない模様. ちなみに出力の際 (ffmpeg ... pipe:1
) はそのままストリーミング再生しても問題ないようだった.
chinachu弄ってたらめちゃ嵌った.