
シェルスクリプトで自分自身を削除するような構文を組んだとしても最後まで実行されました。
しかし、自分自身に別の同名ファイルを上書きコピーした場合は、
中途半端にコピー後のシェルが実行されました。
お聞きしたいのは、
・「削除した場合でもスクリプトは最後まで実行される」という認識は正しいのか
・コピーした場合はどうなるのか
の2点です。
今回試したところ、コピーした場合は2行目の途中からコピー後のスクリプトが実行されたのですが、
これはマシンのスペックによるのでしょうか?
「コピーした場合はどうなるのかわからない」と判断した方がよいでしょうか?
現在、自分自身を修正するようなスクリプトを作成したいのですが、
上記認識で作ってよいのかどうか迷っています。
よろしくお願いします。
▼以下、今回試した内容です。
goというスクリプトを作成しました。
#!/bin/bash
rm -rf ./go
echo "1"
echo "2"
echo "3"
echo "4"
echo "5"
のように書かれています。
これをカレントディレクトリで ./go のように実行します。
実行結果は特にエラーメッセージも出ず、
goスクリプトは消え、1~5がコンソールに表示されました。
ファイル自体を削除されてもスクリプトを終えるまではコマンドは生きているように見えます。
上記goファイルのrm -rf ./goを、
cp -rf ../go .
に修正し、
上の階層に同名のgoスクリプトを用意します。
こちらのgoには
#!/bin/bash
cp -rf ../go .
echo "A1"
echo "A2"
echo "A3"
echo "A4"
echo "A5"
と書いています。
この状態で、最初の階層でgoを実行します。
最初の実験結果から、
・カレントのgoの内容は上の階層のgoをコピーされたもの(echo "A1"~の方)になる。
・コンソールには1~5が表示される
と考えました。
実際は、当然goファイルは上の階層のgoをコピーしたものになりましたが、
コンソールには、
./go: A1: command not found
A2
A3
A4
A5
と表示されました。
2行目の途中から、上の階層のgoの内容が実行されているように見えます。
また2回目の環境でコードを、
#!/bin/bash
rm -rf ./go
cp -rf ../go .
echo "1"
echo "2"
echo "3"
echo "4"
echo "5"
にした場合は、コンソールに表示されたのはA1~A5ではなく1~5でした。
▲上記が試した内容です。
No.3ベストアンサー
- 回答日時:
まずunix/linuxのファイルシステムの基本として、rm しただけではファイルは消えません。
オープン中のファイルをrmした場合、そのファイルをオープンしているプロセスがすべて終了した段階で削除されます。それまでは元のファイルが読み書きされます。シェルは、一文ずつファイルから読み込んで実行します。実行中にファイルが上書きされることは想定していないので、cp で上書きした場合は、cp文の末尾のバイト位置の次から読み続けられます。従って、新しいファイルの途中から続行されることになります。そのバイト位置が新しいファイルで文の途中であれば、おそらくエラーになりますね。試された状況では、ファイルの前半が同じなのでちょうどうまく続行できたわけです。
rm して cp した場合は上書きではありませんので、最初に書いたとおり、シェルはrmした古いファイルを読み続けることになります。
回答ありがとうございます。
よくわかりました。
rmでいきなり消えるわけじゃないんですね。
LinuxはWindowsと違って消したらアウトみたいなイメージがありましたけど。
少し前に作ったスクリプトは、テストして巧く動いたので使い始めましたが、
テスト中は「ちょうどうまく続行できた」だけであることがわかりました。
あああ早く修正してこないと…。
No.2
- 回答日時:
>bashが何をしているのかについては何を見たらよいのかわからないのですが
GNU-BashはGNU精神に基づきソースコードが公開されている(バージョンによってはソースコードを自前でコンパイルしてインストールする)ので、GNUソースコードライブラリを参照し、ソースコードを読んで下さい。
ソースコードを読めば、bashが何をしているか判ります。
No.1
- 回答日時:
「OSのバージョンと、bashの実装に依存する」が答え。
もしbashが「スクリプトをオープンしたまま」であれば「オープン中のファイルを削除しようとした場合にrmはどういう挙動にでるか?」って事になる。
もしbashが「スクリプトを1行実行する度に、fgetsで1行づつ読み込みしている」であれば「オープン中のファイルに上書きした場合にfgetsはどういう挙動にでるか?」って事になる。
もしbashが「スクリプトを最初に全部読み込んでしまう」であれば「実行開始したら自己の変更は不可能」って事になる。
で、OSが変われば(FreeBSDとかSoralisとかLinuxとか)bashの実装方法も変わるし、rmやcpやfgetsの実装方法も異なる。
つまり「今の、その環境ででは、そう動く。環境が変わったら同じ動きをする保証はどこにもない」と言う事。
環境によっては「core吐いて止まる」かも知れませんよ。
回答ありがとうございます。
よくわかったような気がします。
bashが何をしているのかについては何を見たらよいのかわからないのですが、
(試してみるしかないわけじゃないと思いますが)
このディストリビューションで同じようにインストールしたもの(デフォルト状態)であれば同じ動きをする、
ということはわかったので問題なさそうです。
使おうとしている環境は同じですので。
挙げた例の、
rm -rf ./go
cp -rf ../go .
を使って修正(更新)してみようと思います。
ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
インストールできないですどう...
-
LinuxでWine使うとどのくらいWi...
-
ログにserver reached MaxReque...
-
VirtualBox 6.1 → 7.1 でUbuntu...
-
Core 2 Duo の古いパソコンに最...
-
「トゥ]の出し方
-
WinSCPでLinux(CentOS6.10)に...
-
Ubuntu の LibreOffice について
-
ssh接続しようとしたらエラーメ...
-
Linuxのパーティション番号の変...
-
LinuxのノートパソコンでDVDコ...
-
ssl_error_logのエラー内容(AH...
-
bashでシングルクォート内の変...
-
Linux のシェルスクリプトの強...
-
ubuntuのシャットダウンが進ま...
-
AWSのEC2のZabbixユーザーでaws...
-
[Linux Mint] インストールした...
-
zorin OS
-
ubuntu 24 へのCanon 複合機ス...
-
私のパソコンでVirtualBoxは使...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
コマンド終了ステータス
-
実行中のシェルスクリプト自体...
-
OSがプログラムをどのように実...
-
UNIX Cシェルで実数の比較
-
デフォルトシェルの調べ方
-
cshの標準出力を制御したい
-
Bシェルでパイプ→exitがうまく...
-
telnet へのパイプができないです
-
Shellのパターンマッチについて
-
FTPコマンドの戻り値について
-
diskpart でパーティションの一...
-
Bシェル内でのユーザー変更
-
IFS変数について詳しい方教えて...
-
シェルの実行について
-
cygwinシェルスクリプト内での...
-
csh(Cシェル)のevalに関して
-
cshで変数名の入れ子ができない
-
vagrant upでエラーが表示され...
-
cronでftp自動転送を行いたい
-
Mac OSXのターミナルでemacsを起動
おすすめ情報