パイプ付きシェルスクリプト:スクリプト終了キャプチャ

パイプ付きシェルスクリプト:スクリプト終了キャプチャ

2つのシェルスクリプトがあります。 1 つはサーバー上で実行され、いくつかのファイルを一時ディレクトリに書き込みます。その後、ディレクトリはtarアーカイブとしてstdoutに転送されます。最後に(または中断された場合)、一時ディレクトリを削除する必要があります。サーバースクリプト(たとえば、「~/get_dumps.sh」に保存されています)は次のとおりです。

#!/bin/sh
set -e
temp_dir=`mktemp -d`
cd $temp_dir
trap "rm -r $temp_dir; exit" HUP INT TERM PIPE
for db in db1 db2 db3
  do
    pg_dump $db postgres > $db.sql
done
tar cJf - .
rm -r $temp_dir

次のスクリプトを使用して、クライアントからサーバースクリプトを呼び出します。

#!/bin/sh
set -e
temp_dir=`mktemp -d`
trap "rm -r $temp_dir; exit" HUP INT TERM PIPE
mkdir /tmp/dumps
ssh server '~/get_dumps.sh' | tar xJf - -C $temp_dir
ls $temp_dir
rm -r $temp_dir

クライアントスクリプトを実行してCtrl-Cを押すと、クライアントまたはサーバーの両方から一時ディレクトリは削除されません。ここではなぜtrap動作しませんか?

編集:まずset -e

ベストアンサー1

問題はですset -e。複数のコマンドが一緒にパイプされている間にCtrl-cを押すと、SIGINTはスクリプトに送信されず、他の場所に送信されます。これによりエラーが発生し、set -eスクリプトが直接終了するように処理されます。パイプ付きスクリプトで確実に使用するには、次のものもキャプチャする必要がset -eありますEXIT

#!/bin/sh
set -e
temp_dir=`mktemp -d`
cd $temp_dir
trap "rm -r $temp_dir; exit" HUP INT TERM PIPE EXIT
 for db in db1 db2 db3
   do
     pg_dump $db postgres > $db.sql
done
tar cJf - .

この場合、法線はexitトラップによって処理されるため、とにかく多くの状況で役立ちます。

おすすめ記事