'トラップ' killall $$; rm -f $folder2;exit ' 18 20 24

'トラップ' killall $$; rm -f $folder2;exit ' 18 20 24

このコマンドに問題がありますか?

$ trap 'killall $$ ; rm -f $folder2;exit ' 18 20 24

コマンドはforループ内にあり、for実行中に押すとプロセスを停止CTRLし、独自にZ生成されたすべてのファイル(内部的に)を削除したいと思います。folder2folder2

ただし、ターミナルで - を押すとCTRL動作が停止しますが、それ以降は他の操作を実行できず、動作しません。ZCTRLC

答え1

問題は、現在のプロセスPIDを提供している間、killallそのPIDではなくプロセス名と一致するパターンが必要であることです。代わりに$$使用したいですkill

また、ディレクトリとその内容の両方を削除するには、次のよう-rに切り替える必要がありますrm

最後に、プロセスを終了した後に実行するすべての操作は適用されません。kill最後に移動してtrap完全に削除しますexit

trap 'rm -rf "$folder2";kill $$' 18 20 24

for削除する前にループを停止するには、$folder2以下を使用できますbreak

trap 'break;rm -rf "$folder2";kill $$' 18 20 24

答え2

次のスクリプトを例に挙げます。

#!/bin/bash

trap 'echo bye; kill $$' SIGTSTP
sleep 30

睡眠中にControl-Zを押したとしましょう。これにより、SIGTSTP が sleep と bash を含むプロセスグループに送信されます。説明したようにStack Overflowの同様の質問に対するWilliam Pursellの回答trapbashはrun command()が終了するまでハンドラを実行しませんsleep。ただし、スリープは終了しません。 SIGTSTPも受信したため一時停止します。この時点では停止したため、control-C(SIGTERM)、control-\(SIGQUIT) などを無視します。 SIGKILL以外は実行を中止できません。

したがって、trap実行されません(継続的に -9 sleep を終了しない限りすぐに実行されます)。

この問題を解決するには、次のものが必要です。子プロセスを無視するまたは、SIGTSTPを受けずに自分で殺すことを処理してください。またはバックグラウンドで実行してくださいwait

#!/bin/bash

trap 'echo bye; kill $$' SIGTSTP
sleep 30 &
wait

Control-Zは実際に期待どおりに動作します。

関連情報