少し前に、ash
を使用して環境で実行できるはずのbashスクリプトを作成しました。
bash
では次のようになりました:
services=( "service1.service"
"service2.service"
"service3.service" )
for service in "${services[@]}"
do
START $service
done
START()
{
echo "Starting "$1
systemctl start $1
}
実際には40ほどのサービスが並んでいますが、この移行をできるだけ簡単でクリーンなものにしたいと考えています。常にbash
ismsを使用しています。今、私はスクリプトをよりポータブルにするタスクに困っています。
移植性の理由から、おそらく純粋なash
ソリューションを用意するのがいいでしょう。しかし、私は自由に使える非常に堅牢なbusybox
を持っているので、移植性を犠牲にするかもしれません。 「クリーン」スクリプトもメトリックであるため、読みやすさが大幅に向上する場合にのみ。
この場合、portableおよびcleanソリューションは何でしょうか?
配列がbash
、ksh
、およびその他のシェルに入る前は、通常の方法は、要素のいずれにもない区切り文字(または必要なエスケープを最小限に抑えるために一般的ではない区切り文字)を選択することでした)、区切り文字で区切られたすべての要素を含む文字列を反復処理します。シェルはデフォルトで空白文字によって「単語」をすでに分割しているため、通常は空白文字が最も便利な区切り文字の選択です(別のものに分割する場合はIFSを設定できます)。
例えば:
# backslash-escape any non-delimiter whitespace and all other characters that
# have special meaning to the Shell, e.g. globs, parenthesis, ampersands, etc.
services='service1.service service2.service service3.service'
for s in $services ; do # NOTE: do not double-quote $services here.
START "$s"
done
$services
は[〜#〜] not [〜#〜]ここで二重引用符で囲む必要がありますwantシェルが「単語」に分割するためです。
ashには配列がありません。接近するのは位置パラメータだけなので、次のことができます
set -- "service1.service" \
"service2.service" \
"service3.service"
for service in "$@"
do
START $service
done
サービスのリストを一度だけ参照する必要がある場合は、ヒアドキュメントを使用できます。
while IFS= read -r service
do
START "$service"
done << END
service1.service
service2.service
service3.service
END
リストではサービス名を引用符で囲まないでください(ただし、特に理由がない限り、"$service"
は引用符で囲む必要があります)。サービス名をインデントしたい場合は、<<-
の代わりに<<
を使用し、タブで名前をインデントします。
while IFS= read -r service
do
START "$service"
done <<- END
service1.service
service2.service
service3.service
END