실수로 입력을 과도한 페이지 매김으로 파이프한 후 대화형 명령을 재개하시겠습니까?

실수로 입력을 과도한 페이지 매김으로 파이프한 후 대화형 명령을 재개하시겠습니까?

다음과 같은 스크립트를 고려해보세요.

$ 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 를 받습니다 .CtrlCbashsleepless

sleep받으면 죽을 것이니 죽는 것이다 bash. lessSIGINT를 가로채서 다음과 같이 처리합니다.현재 작업 취소.

하지만 bash죽지 않으면 계속해서 읽을 수 있습니다 less.

따라서 당신이 할 수 있는 일은 bashSIGINT가 사망을 초래하는 것을 방지하는 것뿐입니다.

(trap '' INT; bash example.sh) | less

Ctrl그런 다음 +를 사용하여 스크립트에 의해 시작된 프로세스에 영향을 주지 않고 C중단 할 수 있습니다 .lessbash

스크립트를 중지하려면 SIGTERM을 사용하여 CtrlSIGQUIT를 \보낼 CtrlZ있습니다 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

관련 정보