SSH를 사용하여 원격 서버에서 명령을 실행하는 스크립트가 있습니다. 출력의 모든 줄 앞에 문자열을 추가하고 싶지만 Remote:
전체 줄을 사용할 수 있을 때까지 각 줄이 지연되는 것을 원하지 않습니다. 내 명령의 출력은 다음과 같습니다.
$ myproject-db-push my_database_name 데이터베이스에서 내보내는 중... 완료 데이터 보관 중... 완료 아카이브를 원격으로 업로드하는 중... 완료 원격에서 설치 스크립트 실행 원격: 아카이브를 임시 디렉터리로 압축 해제하는 중... 완료 원격: 데이터베이스 사용: my_database_name 원격: 컬렉션 삭제: 원격: - my_collection_foo 원격: - my_collection_bar 원격: 새 데이터를 가져오는 중... 완료
이 경우 sed
다음과 같이 사용하고 있습니다.
echo "$INSTALLCMD" | ssh -T "deploy@$SERVER" | sed -u "s/^/Remote: /"
문제는 내가 설명했듯이부분적인줄이 화면에 인쇄됩니다. 부품 을 제거하면 | sed
예상대로 작동합니다. 먼저 다음과 같이 작성됩니다.
새 데이터를 가져오는 중...
그리고 몇 초 후에 라인이 완성됩니다.
새 데이터를 가져오는 중... 완료
나는 sed
한 줄씩만 작업할 수 있다고 가정합니다. 버퍼링되지 않은 상태로 설정하려고 시도했지만 여전히 전체 라인을 기다립니다. 이를 수행하는 또 다른 방법이 있습니까?
답변1
sed
모든 유틸리티( , awk
, grep
)가 라인 버퍼링되어 있기 때문에 약간 까다롭습니다 . 즉, 줄이 끝났을 때만(새 줄이 나타났을 때) 출력을 인쇄한다는 의미입니다. 입력된 문자를 문자별로 읽을 수 없습니다.
그래서 테스트를 위해 여러분의 행동을 시뮬레이션하는 작은 시퀀스를 만들었습니다.
{
echo -n "first task: "
sleep 2
echo "done"
echo -n "second task: "
sleep 2
echo "done"
}
귀하의 질문과 마찬가지로 first task:
2 초 후에 인쇄됩니다 done
. 터미널에 복사하여 직접 사용해 보세요.
해결책:
명령 뒤에 다음을 추가합니다.
IFS=
command | { x=1; while IFS= read -d'' -s -N 1 char; do
[ $x ] && printf "Remote: "
printf "$char"
unset x
[ "$char" == "
" ] && x=1
done; }
설명:
read
의 내장은 입력 bash
된 문자를 문자별로 읽을 수 있습니다. 이 부분은 read -d'' -s -N 1 char
구분 기호를 비활성화 -d''
하고 자동 모드를 활성화하며 변수에 -s
한 번에 한 문자만 읽습니다 . 그런 다음 명령은 변수가 존재하는지 확인합니다. 그렇다면 새 줄에 있고 "접두사"를 인쇄합니다. 그런 다음 문자를 인쇄합니다. 설정 해제 . 그런 다음 마지막 명령문은 문자가 개행인지 확인합니다. 다음 루프에 개행 문자가 설정 되어 있으면 "접두사"가 인쇄됩니다.-N 1
$char
$x
$x
$x
1
두 시퀀스를 연결하면 모든 것을 테스트할 수 있습니다.
{
echo -n "first task: "
sleep 2
echo "done"
echo -n "second task: "
sleep 2
echo "done"
} | { x=1; while IFS= read -d'' -s -N 1 char; do
[ $x ] && printf "Remote: "
printf "$char"
unset x
[ "$char" == "
" ] && x=1
done; }