通常、スクリプトを編集すると、そのスクリプトを実行しているすべての目的でエラーが発生しやすくなります。
例:
sleep 20
echo test
このスクリプトを実行すると、bashは最初の行(たとえば10バイト)を読み取り、スリープモードに入ります。回復すると、バイト 10 から始まるスクリプトの内容が異なる場合があります。まったく異なる分岐の異なる行の途中で実行が開始されることがありますif
。実行中のスクリプトが削除されます。
それでは、後で編集しても実行中のインスタンスに影響を与えないように実行する前に、シェルスクリプト全体をどのように読み取ることができますか?
ベストアンサー1
はい、シェルはbash
ファイルを一度に1行ずつ読み込むことに特別な注意を払います。したがって、インタラクティブに使用するのと同じ方法で動作します。
ファイルを検索できない場合(パイプなど)、bash
一度に 1 バイトずつ読み取ってその\n
文字だけを読み取ることがわかります。ファイルを検索できる場合は、ブロック全体を一度に読み取って最適化しますが\n
。
これは、次のことができることを意味します。
bash << \EOF
read var
var's content
echo "$var"
EOF
または、自分で更新するスクリプトを作成してください。その保証を提供しないと、そうすることはできません。
今、私はこのようなことをしたくないかもしれませんが、この機能が役に立つよりも邪魔になることが多いことがわかります。
これを回避するには、ファイルを所定の場所に変更しないようにすることができます(たとえば、コピーを変更してからコピーを所定の場所に移動します(たとえば、sed -i
一部のperl -pi
編集者が実行する操作など)。
または、次のようにスクリプトを作成できます。
{
sleep 20
echo test
}; exit
(閉じ括弧の直前の中かっこ内に入れることもできますが、exit
;と同じ行にあることが重要です。)}
または:
main() {
sleep 20
echo test
}
main "$@"; exit
タスクの実行を開始する前に、シェルはスクリプトを読み取る必要がありますexit
。これにより、シェルはスクリプトから再度読み取られなくなります。
これはスクリプト全体がメモリに保存されることを意味します。
これはスクリプトの解析にも影響します。
たとえば、次のようになりますbash
。
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
UTF-8でエンコードされたU + 00E9を出力します。ただし、次のように変更すると:
{
export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'
}
\ue9
コマンドの解析時に適用された文字セットに展開されます。この場合今後コマンドがexport
実行されます。
source
また、akaコマンドを使用する場合、.
一部のシェルではソースファイルと同じ問題が発生します。
bash
ただし、このコマンドはファイルを解釈する前にsource
ファイルを完全に読み取るため、そうではありません。具体的に書かれている場合は、bash
スクリプトの先頭に以下を追加することで実際にそれを利用できます。
if [[ ! $already_sourced ]]; then
already_sourced=1
source "$0"; exit
fi
(私はこれに依存しません。将来のバージョンではこの動作が変更される可能性があると想像できますが、これは現在の制限と見なすことができますbash
(bashとAT&T kshは、私たちが知っている限りPOSIXのように動作する唯一のシェルです) . already_sourced
BASH_SOURCE 変数の内容に影響を与えるということは、言うまでもなく、変数が環境にないと仮定するため、少し脆弱です。