GNU/Linux >> Linux の 問題 >  >> Linux

実行する前にシェルスクリプト全体を読む方法は?

通常、スクリプトを編集すると、実行中のスクリプトの使用法はすべてエラーになりがちです。

私が理解している限り、bash(他のシェルも?)はスクリプトを段階的に読み取るため、スクリプトファイルを外部で変更すると、間違ったものを読み取り始めます。それを防ぐ方法はありますか?

例:

sleep 20

echo test

このスクリプトを実行すると、bashは最初の行(たとえば10バイト)を読み取り、スリープ状態になります。再開すると、10バイト目から始まるスクリプトの内容が異なる場合があります。新しいスクリプトの行の途中にいる可能性があります。したがって、実行中のスクリプトは壊れます。

承認された回答:

はいシェル、およびbash 特に、ファイルを一度に1行ずつ読み取るように注意してください。これにより、インタラクティブに使用する場合と同じように機能します。

ファイルが(パイプのように)シークできない場合は、bash \nを超えて読み取らないように、一度に1バイトずつ読み取ることもできます。 キャラクター。ファイルがシーク可能である場合、一度に完全なブロックを読み取ることで最適化されますが、\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 "[email protected]"; 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 コマンドが実行されます。

関連:SSH –ネットワークのscpを自動化するスクリプト?

sourceの場合も注意してください 別名. コマンドが使用されますが、一部のシェルでは、ソースファイルに対して同じ種類の問題が発生します。

bashの場合はそうではありません そのsource コマンドは、ファイルを解釈する前にファイルを完全に読み取ります。 bash用に作成する場合 具体的には、スクリプトの先頭に次を追加することで、実際にそれを利用できます。

if [[ ! $already_sourced ]]; then
  already_sourced=1
  source "$0"; exit
fi

bashの将来のバージョンを想像できるので、私はそれに依存しません。 現在制限と見なされている動作を変更する可能性があり(bashとAT&T kshは、可能な限りそのように動作する唯一のPOSIXのようなシェルです)、already_sourced トリックは、変数が環境内にないことを前提としているため、少し脆弱です。もちろん、BASH_SOURCE変数の内容に影響を与えることもあります)


Linux
  1. シェルスクリプトで外部IPアドレスを取得する方法は?

  2. Bashスクリプトをデバッグする方法は?

  3. シェルスクリプトを暗号化またはレンダリングして判読不能にする方法は?

  1. .bashrcの目的とそれはどのように機能しますか?

  2. ターミナルでループバッシュスクリプトを停止する方法は?

  3. BASH シェルが Linux で構成ファイルをロードする方法

  1. Unix コンソールまたは Mac 端末でシェル スクリプトを実行するには?

  2. Bashを使用してファイルの最後から2番目の行を読み取る方法は?

  3. シェルスクリプト、メッセージをエコーし​​た後に同じ行で読む