実行中にbashスクリプト(.sh)ファイルを変更できますか?


28

script.sh実行に時間がかかるスクリプトがあるとします。実行し./script.shます。ターミナルウィンドウで実行中に、ファイルを変更しますscript.sh。これはすでに実行中のプロセスに影響を及ぼしますか?

それを変更した後、変更したファイルを実行するので、2つの実行中のプロセスがあります。これでいいですか?


回答:


36

スクリプトを変更すると、ディスク(ハードディスク-永続ストレージ)に変更が加えられます。スクリプトを実行すると、スクリプトがメモリ(RAM)にロードされます。

そのため、スクリプトに加えた変更は実行中のスクリプトに影響を与えません。変更を加える前に実行したバージョンを実行します。

ただし、以前に実行したインスタンスを終了せずに、変更したスクリプトを再度実行すると、スクリプトの2つのインスタンスがあります。1つは変更があり、もう1つは古いインスタンスです。

スクリプトが使用および変更するリソースが競合することに注意してください。たとえば、スクリプトを使用してファイルを変更している場合、後で実行するスクリプトはそのファイルを書き込み用に開くことができず、正しく実行できません。

更新: 登録ユーザーに、Unix.stackexchange.comでより良い答えを教えてくれてありがとう。

スクリプトのサイズと問題のコンパイラ/インタープリターに応じて、スクリプトは部分的/完全にロードされます。そのため、スクリプトが完全にロードされていない場合、スクリプトの一部がメモリにロードされると、スクリプトに加えた変更が実行中のインスタンスに反映されます。

したがって、予測不能な出力のために現在実行中のディスク上のスクリプトを変更することはお勧めしません。最初に実行中のインスタンスを停止してからスクリプトを変更してから、スクリプトを再実行します。


11
完全な答えではありません。unix.stackexchange.com/ q / 121013/55673
登録ユーザー

@registereduser:そうそう、その質問はOSの教訓を思い出させてくれました。私は(今の自分の携帯電話上で)私のデスクトップに私の手を取得するとすぐに私の答えを編集します
ジョバン

短いスクリプトの場合は問題ないはずです。
becko

1
bash v3.2.48(こちらを参照)でこれを試したところ、行末を超えてバッファリングされませんでした(実行時にスクリプトを変更したときにひどく失敗しました)。bash v4.3.0で再テストしたところ、(短い)スクリプト全体がバッファリングされました。だから...私は特定の行動に頼りません。
ゴードンデイヴィソン14年

1
@RegisteredUser bashのすべてのバージョンではありません。リンクした例を参照してください。
ゴードンデイヴィソン14年

4

他の回答では言われていないと思うことを追加します。ファイルの編集方法に大きく依存します。こうecho "stuff" >fileシェル(別のインスタンス)からは、実際に私が思うに、ファイルを上書きします。ただし、たとえばファイルを編集してemacsから保存すると、これは起こりません。代わりに、ここでエディタは古いファイルの名前を何らかのバックアップ名に変更し(実際には以前のバックアップを削除する場合があります)、変更されたバッファの内容を(現在はlibreatedされた)古い名前の新しいファイルとして書き込みます。スクリプトを読み取るシェル(または他のインタープリター)はほぼ確実に1回だけファイルを開くため、その後はファイル名の所在に依存しません、開いた時点でファイル名に関連付けられていた物理ディスクファイル(iノード番号で識別)の読み取りを続行します。そのため、スクリプトをブロック単位で読み取る場合でも(これは、バッファリングされたテキストI / Oを使用する場合の最も簡単なソリューションです)、ファイルの古いインスタンスから行を読み取り続けるため、編集によって変更されない可能性があります。


+1 Sublime Textをエディターとして使用しています。のようにファイルの名前も変更されるかどうか知っていますemacsか?
becko 14年

1
ほとんどの編集者は、(バックアップバージョンを保持してはならない場合でも)名前変更スキームを使用して、書き込みプロセス中にクラッシュが発生した場合、テキストの完全なバージョンがまったく残らないというリスクを回避すると思います。「ls -i」(iノード番号を表示)を使用して、エディターの動作を確認できます。
マークヴァンレーウェン14年

1

これは更新する必要があり、上記の答えは部分的に正しいだけです:

現在のバージョンのbashでは、実行中のディスク上のスクリプトを変更すると、bashが変更をメモリにロードし、実行中のスクリプトでそれらを引き継ぐようになります。変更が現在実行中の行の後に来る場合、新しい行がロードされて実行されます。しかし、これはbashによる推測であり、正しいか間違っている可能性があります。

これを行うためのより良い方法は、次の一連のアクションです:1)スクリプトをメモリにロードする2)スクリプトをディスクから削除する3)最初にディスクバージョンを削除して新しいスクリプトをディスクに書き込む、メモリバージョンはリンクを失うステップ3で新しいバージョンを指定すると、bashによる新しいバージョンのメモリバージョンへのロードは試行されません。


0

@jobinの答えは一般的に正しいですが、あなたが何をしたいのかによってポイントになるかもしれない他の答えをいくつか追加します。

スクリプトを変更し、安全であることを知りたい場合は、既存のファイルではなく、新しいファイルに書き込みたい場合、新しいファイルは古いファイルがあった場所に配置できます。新しいバージョンを新しいファイルに書き込み、それを使用mvして古いバージョンの上に移動します。置き換えられたファイルはまだ存在し、ディレクトリからリンクされていないだけです。実行中のスクリプトはそれを使用し続けることができ、そのスクリプトがファイルハンドルを閉じると、システムはファイルを安全にクリーンアップできることを(すぐにでも後ででも)知っています。

スクリプトの動作をその場で動作させたい場合は、より難しい問題があります。スクリプトのコードに組み込む必要があると思います。Bashスクリプトはシグナルを処理でき(例:などをキャッチできますkill -USR1 [pid])、スクリプトはコードをリロードすることで応答できます。あなたが望むものに近い機能を得ることができるかもしれませんが、あなたが何を求めているのか分からずに、私はこれを行う正当な理由を見ていません。それを行うプログラミング言語。

これを念頭に置いて書かれていない実行中のスクリプトの動作をハックしたい場合は、運が悪いです。プログラミングタスクを不可能と呼ぶことをheしますが、この種のタスクのためのリソースとスキルがあれば、おそらくここで尋ねることはないでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.