
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 -$key
SIGHUP
nohup
簡単な実験でこれを確認できます。
$ alacritty -e sh -c 'nohup sleep 1000 &'
$ pgrep -a sleep
$
strace
コマンド全体はブランチを表示しますが、ブランチプロセスがブランチを受信し(終了して生成された疑似端末が消えた場合)、終了するまで実行されませsh
んexecve
。nohup
SIGHUP
alacritty
ターミナルとグラフィックアプリケーションを混在させるときに存在する可能性がある代替策を見つけることなく、合理的な解決策は、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
また見なさい:
- バックグラウンドで開始する前にプロセスが終了しました。- 非常によく似た質問に対する回答には、より多くの説明と興味深い解決策があります。
- nohupの代わりに&と出力リダイレクトを使用するのは安全ですか?- 私の職業管理ベースの選択肢がどのように等しくないかについて
nohup
。