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
죽지는 않았습니다.
두 번째 방법(새 터미널 창에서 스크립트 작성)은 5번에 한 번씩 작동할 수 있습니다. 다른 경우에는 영역을 선택할 때 커서가 십자선으로 바뀌지 않습니다. 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
.