nohupを使用して呼び出されたスクリプトは、呼び出しスクリプトが終了すると時々終了します。

nohupを使用して呼び出されたスクリプトは、呼び出しスクリプトが終了すると時々終了します。

screenshot-menu.bashスクリーンショットメニュー()を表示する小さなbashスクリプトを作成しました。

#!/usr/bin/env bash
echo 'Select an option:

s whole screen
w active window
r select region
'
read -rsn1 key
sleep 0.1

case $key in
  s|w|r) nohup ./screenshot.bash -$key & ;;
  *) echo Canceled. >> ./log.txt ;;
esac

スクリプトはnohup ./screenshot.bashパラメータを使用して実行されます。これはscreenshot.bash

#!/usr/bin/env bash
while [[ "$#" > 0 ]]; do case $1 in
  -s|--screen) PARAM=''; TYPE='Screen'; shift;;
  -w|--window) PARAM='-u'; TYPE='Window'; shift;;
  -r|--region) PARAM='-s'; TYPE='Region'; shift;;
  *) echo "Unknown parameter passed: $1"; exit 1; shift; shift;;
esac; done

sleep 0.2
scrot $PARAM $(xdg-user-dir PICTURES)/'%Y-%m-%d %H.%M.%S $wx$h '$TYPE.png -e 'echo "$f" && notify-send -u low "$f"'

./screenshot-menu.bashターミナル内で実行してからを入力すると、rすべてがうまく機能します。ゾーンを選択してそのゾーンのスクリーンショットを取得できます。

しかし、私はこのスクリプトをどこでも呼び出せるようにしたいと思います。これが新しい端末ウィンドウでこのスクリプトを実行するためのキーバインディングがある理由です。

alacritty -t "Screenshot menu" -o "window.dimensions.columns=20" -o "window.dimensions.lines=7" -e ~/bin/screenshot-menu.bash

(またはより簡単ですgnome-terminal -- ~/bin/screenshot.bash。)

これが私が使用するものですnohup。スクリーンショットに表示されたくないので、端末を終了したいと思います。しかし、もちろんscreenshot.bash死ぬことはありませんでした。

2番目の方法(新しいターミナルウィンドウでスクリプトを作成)は、5回に1回操作できます。それ以外の場合は、領域を選択してもカーソルが十字線に変わりません。screenshot.bash使っても死んだと思いましたnohup

このランダム動作の原因は何ですか?

ベストアンサー1

問題は、screenshot-menu.bashバックグラウンドフォークで実行されているプロセスが実行される前にaを受信して​​終了する可能性が高いです。nohup ./screenshot.bash -$keySIGHUPnohup

簡単な実験でこれを確認できます。

$ alacritty -e sh -c 'nohup sleep 1000 &'
$ pgrep -a sleep
$

straceコマンド全体はブランチを表示しますが、ブランチプロセスがブランチを受信し(終了して生成された疑似端末が消えた場合)、終了するまで実行されませshexecvenohupSIGHUPalacritty

ターミナルとグラフィックアプリケーションを混在させるときに存在する可能性がある代替策を見つけることなく、合理的な解決策は、nohupバックグラウンドに移動するコマンドに適用することを避け、代わりに親プロセスで使用することです。たとえば、

$ alacritty -e sh -c 'nohup sh -c "sleep 1000 &"'
$ pgrep -a sleep
625910 sleep 1000

screenshot-menu.bashこの行を適切に変更できます

s|w|r) nohup ./screenshot.bash -$key & ;;

入力する

s|w|r) nohup sh -c "./screenshot.bash \"-$key\" &" ;;

あるいは、screenshot-menu.bashジョブ制御を有効にしてset -m削除することもできますnohup(シェルは独自のプロセスグループからバックグラウンドパイプ(簡単なコマンドもパイプ)を起動し、SIGHUP端末を制御する場合はフォアグラウンドプロセスグループのみが渡されます)が消えます。 、screenshot.bash端末で読み書きする試みがないことを確認できる場合(つまり、実行したのと同じ明示的なリダイレクトが必要nohup

たとえば、screenshot-menu.bash次のようになります。

#!/usr/bin/env bash

set -m

echo 'Select an option:
...
'

case $key in
  s|w|r) </dev/null >>./log.txt 2>&1 ./screenshot.bash "-$key" & ;;
  *) echo Canceled. >>./log.txt ;;
esac

また見なさい:

おすすめ記事