저는 ssh 및 rsync와 관련된 일종의 백업을 위한 스크립트를 작성 중입니다. 스크립트를 실행할 때마다 모든 출력을 로그 파일로 리디렉션합니다. 로그 항목을 표준화하기 위해 타임스탬프와 로그 수준을 추가하는 로그 함수를 작성했습니다. 내 생각은 각 명령줄의 stdout 및 stderr을 한 줄씩 읽고 해당 로그 함수를 호출하는 것입니다. 그래서 아래 답변을 따랐습니다.https://serverfault.com/questions/526592/pipe-stderr-and-stdout-to- Different-commands-not-just-to-files.
내 스크립트는 다음과 같습니다(사용된 모든 변수가 올바르게 설정되었다고 가정하면 축소됨).
#!/bin/bash
# function: print a formatted log message including timestamp with given level and message to stdout
# arguments: <LEVEL> <MESSAGE>
log()
{
timestamp=$(date +"%F %T.%3N")
level=$1
message=$2
echo $timestamp $level: $message
}
# function: read command output from stdin and log it with given level
# arguments: <LEVEL>
logoutput()
{
sed 1d | \
while read i
do
log "$1" "$i"
done
}
log INFO "START ssh"
(ssh $connection mkdir -p $destStaticDirectory | logoutput INFO) 3>&1 1>&2 2>&3 | logoutput ERROR
log INFO "START rsync"
(rsync $rsyncArguments $linkDest $fromDirectory $connection:$destStaticDirectory | logoutput INFO) 3>&1 1>&2 2>&3 | logoutput ERROR
이 기능은 log()
로그 항목을 에코하는 데 사용되며, 이 기능은 한 줄씩 읽고 각 줄을 기록하는 logoutput()
데 사용됩니다 .stdout
이제 문제는 모든 것이 rsync 명령에 의해 예상대로 작동한다는 것입니다. 하지만 ssh 명령에서는 작동하지 않습니다. ssh $connection mkdir -p $destStaticDirectory
올바르게 호출되면 stdout에 출력이 없다는 것을 알고 있습니다 . 그래서 ssh를 알 수 없는 호스트에 연결하여 테스트했는데 결과는 ssh: Could not resolve hostname XXX: Name or service not known
... 그러나 아무것도 아닙니다. 또한 모든 출력을 예상대로 인쇄하는 동일한 ssh 명령 "unwrapped"를 스크립트에 추가했습니다. 마지막으로 SSH의 상세 모드를 켜서 오류 로그 항목이 발생했습니다. 그러나 내 로그에 SSH 버그 메시지가 표시되는 것을 원하지 않기 때문에 이것은 옵션이 아닙니다.
내가 뭐 놓친 거 없니? ssh가 수행하는 것과 동일한 이상한 stdout,err 처리가 있는데 내가 알지 못하는 걸까요? 내가 하려는 일이 무엇인지 분명히 밝혔기를 바랍니다.
답변1
문제는 "sed 1d"가 찾고 있는 출력을 제거하는 로그 출력 기능에서 발생할 가능성이 높습니다. "sed 1d" 줄을 제거하고 스크립트가 예상대로 실행되는지 확인하세요.
답변2
사용을 고려해 보셨나요?로거(1)로깅이 자동으로 수행되고 타임스탬프 등이 추가됩니다.
그럼 좋아
{ ssh ... | logger ...; } 2>&1 | logger ...
첫 번째 부분은 로거를 통해 stdout을 로그 파일로 보내고 두 번째 부분은 stderr을 로그 파일로 보내기 때문에 원하는 것이어야 합니다. 로거 명령줄 옵션을 사용하여 로깅 기능이나 파일 등을 선택할 수 있습니다.
이 작업을 수행하는 더 깔끔한 방법도 있습니다. 사용프로세스 교체예를 들어
ssh ... > >(logger ...) 2> >(logger ...)
이렇게 하면 모든 파일 설명자를 저글링할 필요가 없습니다.