다음과 같은 스크립트를 고려해보세요.
$ cat example.sh
#! /usr/bin/env bash
for i in {1..90}
do
printf '%s\n' "$i"
done
sleep 10
printf '91\n'
sleep 10
printf 'done\n'
출력이 다음과 같이 덜 파이프된다고 가정합니다.
$ bash example.sh | less
90행까지 아래로 스크롤하면 다시 위로 스크롤하여 검색하고 less
제공된 다른 대화형 명령을 사용할 수 있습니다. 그러나 eg j
또는 line 90 을 사용하려고 하면 Ctrl-N
다른
less
입력 라인을 사용할 수 있을 때까지 대화형 명령에 대한 응답이 중지됩니다. 스페이스바를 사용하여 90행을 지나 전체 페이지를 스크롤하려고 하면
less
전체 페이지 입력이 가능하거나 EOF가 수신될 때까지 대화형 명령에 대한 응답이 중지됩니다.
이전 출력을 보고 싶고 사용 가능한 행을 탐색했으며 더 많은 행이 나타날 때까지 기다려야 한다는 사실을 인식하지 못하는 경우(임의의 시간이 걸릴 수 있음) 이는 권장되지 않을 수 있습니다.
Ctrl-C를 사용하여 SIGINT를 보내면 즉시 다시 상호 작용을 얻을 수 있지만 less
파이프에서 더 많은 입력을 수신하는 것이 중지됩니다.
이 스크립트는 재현하기 쉬운 예일 뿐이지만 깨진 심볼릭 링크 찾기와 같이 출력 줄을 천천히 생성하는 장기 실행 명령으로 대체될 수 있습니다.
$ find $HOME -xtype l | less
또는 내 홈 디렉터리에서 누구나 읽을 수 있는 권한:
$ find $HOME -perm 777 | less
또는 stdout
.
less
파이프에서 필요한 입력 줄이 생성될 때까지 기다리지 않고 더 많은 입력을 기다리지 않고 대화형 명령으로 돌아가도록 할 수 있는 방법이 있습니까 ?
답변1
존재하다
bash example.sh | less
전체 파이프가 전경에 배치됩니다(전경 프로세스 그룹에는 실행 중인 프로세스 bash
와 생성된 모든 프로세스가 모두 포함되어 있음). 따라서 +를 less
누르면 모두 SIGINT 를 받습니다 .CtrlCbash
sleep
less
sleep
받으면 죽을 것이니 죽는 것이다 bash
. less
SIGINT를 가로채서 다음과 같이 처리합니다.현재 작업 취소.
하지만 bash
죽지 않으면 계속해서 읽을 수 있습니다 less
.
따라서 당신이 할 수 있는 일은 bash
SIGINT가 사망을 초래하는 것을 방지하는 것뿐입니다.
(trap '' INT; bash example.sh) | less
Ctrl그런 다음 +를 사용하여 스크립트에 의해 시작된 프로세스에 영향을 주지 않고 C중단 할 수 있습니다 .less
bash
스크립트를 중지하려면 SIGTERM을 사용하여 CtrlSIGQUIT를 \보낼 Ctrl수 Z있습니다 kill %
.
여기서 1은 SIGINT로 인해 종료됩니다. SIGINT가 정상적으로 처리되고 종료 bash
되면 sleep
상황이 달라집니다. 이는 sleep
다른 쉘에서 수행되는 특수 SIGINT 처리입니다.bash
답변2
귀하의 질문을 올바르게 이해했다면 귀하가 원하는 동작은 수면을 중단하고 대화형 vim
모드 로 돌아가는 것입니다 :
.
그 답은 sleep 함수를 어떻게 처리하느냐에 달려 있는데, 그 sleep
자체로는 일반적인 쉘 명령이 아니라 특정 시간에 실행되는 더미 작업을 생성하는 아주 특별한 명령이므로 인터럽트 처리를 고려해야 합니다. 그러나 스크립트를 수정하면 동작을 쉽게 달성할 수 있습니다.
#!/bin/bash
trap 'kill $(jobs -p)' INT
for i in {1..90}
do
printf '%s\n' "$i"
done
sleep infinity &
wait
printf '91\n'
sleep 10 &
printf 'done\n'
테스트를 위해 무기한 대기 상태가 되도록 원본 스크립트를 일부 수정했습니다.
90번 라인에 도달하여 지나가려고 하면 시스템이 sleep
오래 걸릴 것입니다. 종료하려면 을 클릭하세요 CTRL+C. 신호 트랩 덕분에 sleep
작업이 중단될 뿐만 아니라 원하는 콘텐츠 :
와 해당 기능도 반환됩니다(실행 후 키를 눌러야 할 수도 있음 CTRL+C). 또한, 다시 90번째 줄을 지나 이동하려고 하면 스크립트 실행이 첫 번째 작업을 지나 이동했기 때문에 91번째 줄이 즉시 인쇄됩니다 sleep
.
답변3
가장 덜 나쁜 해결책은 다음을 사용하는 것입니다 setsid(1)
.
setsid bash example.sh | less
또는
setsid find $HOME -xtype l | less
또는
setsid find $HOME -perm 777 | less
"가장 나쁜 점"은 setsid(1)
명령으로서 비표준 Linux-ism이므로 아직 사용할 수 없는 경우 가장 가까운 패키지 관리자에서 설치해야 할 뿐만 아니라(사실 이식 가능) 문제의 명령이 다음과 같기 때문입니다. 또한 직업 통제에서 벗어날 수 있으므로진짜ps x
멈춰 있고 발견된 PID를 사용하여 수동으로 kill 명령을 사용하는 것 외에는 선택의 여지가 없습니다 .
다른 옵션도 있지만 모두 휴대성이나 인체공학적 문제가 있습니다. 비교하다:https://unix.stackexchange.com/a/736048/54340