![eval을 사용하여 첫 번째 파이프라인 명령의 반환 코드를 얻으시겠습니까?](https://linux55.com/image/150208/eval%EC%9D%84%20%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC%20%EC%B2%AB%20%EB%B2%88%EC%A7%B8%20%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8%20%EB%AA%85%EB%A0%B9%EC%9D%98%20%EB%B0%98%ED%99%98%20%EC%BD%94%EB%93%9C%EB%A5%BC%20%EC%96%BB%EC%9C%BC%EC%8B%9C%EA%B2%A0%EC%8A%B5%EB%8B%88%EA%B9%8C%3F.png)
다른 명령을 실행하고 스크립트의 후속 단계를 계속하기 전에 반환 코드를 확인하고 싶습니다. 동시에 tee 명령을 사용하여 실행된 명령의 출력을 파일에 기록하고 싶습니다. 예:
#set non-existing folder
local_path="~/njn"
log_path_file="test.log"
cmd="ls -l ${local_path} | tee -a ${log_path_file}";
eval ${cmd}
returncode=$?
echo "execution result: ${returncode}" | tee -a ${log_path_file};
if [ ${returncode} -eq 0 ]; then
echo "success" | tee -a ${log_path_file}
else
echo "not success" | tee -a ${log_path_file}
fi
반환 코드는 0입니다. 0보다 커야 합니다.
returncode 변수가 실행된 명령(이 경우 ls -l 명령)의 실제 반환을 가지기를 원합니다.
파일을 사용하여 명령 출력을 작성한 다음 파일에서 반환 코드를 읽는 솔루션이 있습니다(여기), 하지만 저는 좀 더 우아한 해결책을 찾고 있습니다.
답변1
ls -l
이 특별한 경우에는 종료 상태를 실행하고 조치를 취하는 것이 더 쉬울 것입니다.
if ls -l "$local_path"; then
echo 'success'
else
printf 'failure (code %d)\n' "$?"
fi | tee -a "$log_path_file"
bash
셸 에서는 배열의 값을 탐색할 수도 있습니다 PIPESTATUS
.
$ false | true | true | false | false
$ printf '%s\n' "${PIPESTATUS[@]}"
1
0
0
1
1
귀하의 경우:
ls -l "$local_path" | tee -a "$log_path_file"
ls_status=${PIPESTATUS[0]}
if [ "$ls_status" -eq 0 ]; then
echo 'success'
else
printf 'failure (code %d)\n' "$ls_status"
fi | tee -a "$log_path_file"
답변2
명령을 인수로 사용하고 tee
출력(stdout 및 stderr)을 로그 파일로 보내는 함수를 사용할 수 있습니다.
local_path="~/njn"
log_path_file="test.log"
function log_cmd ()
{
{
"$@"
returncode=$?
if [ "$returncode" -eq 0 ]; then
echo "[successfully executed \"$@\"]"
else
echo "[failed to execute \"$@\", exit code: ${returncode}]"
fi
return $returncode
} 2>&1 | tee -a "$log_path_file"
# return exit code of first command in pipeline
return ${PIPESTATUS[0]}
}
log_cmd ls -l "$local_path"
log_cmd echo "hello world"
답변3
몇 가지 추가 테스트 후에 이 코드 스위치가 훌륭하게 마무리되어 실행된 명령 반환 코드를 반환한다는 사실을 발견했습니다. @Freddy가 게시한 코드는 거의 완성되었습니다. 반환 코드는 함수 내부로 내보내지지만 함수 외부로는 내보내지 않습니다.
shopt -s lastpipe의 사용은 이 페이지에서 가져왔습니다:Bash FAQ 항목 #24: "루프에 변수를 설정했습니다. 왜 루프가 종료된 후 갑자기 사라지나요? 아니면 왜 파이프를 통해 데이터를 읽을 수 없나요?"
이것이 최종 작업 솔루션입니다.
#!/bin/bash
log_path_file="./logs/test.log"
exe_cmd()
{
echo "`date +%Y-%m-%d---%r` [Info]: Command to execute: $@" | tee -a ${log_path_file};
echo "" | tee -a ${log_path_file};
echo "" | tee -a ${log_path_file};
set +m
shopt -s lastpipe
cmdResult=0
{
"$@"
returncode=$?
# save result code
cmdResult=${returncode}
if [ "$returncode" -eq 0 ]; then
echo "`date +%Y-%m-%d---%r` [Info]: successfully executed \"$@\""
else
echo "`date +%Y-%m-%d---%r` [Info]: failed to execute \"$@\", exit code: ${returncode}"
fi
} 2>&1 | tee -a "$log_path_file"
echo "`date +%Y-%m-%d---%r` [Info]: cmdResult result ${#cmdResult[@]}"
return ${#cmdResult[@]};
}
cmd="scp some_user@$some_host:some_path/* a_local_path/sub_path";
exe_cmd ${cmd}
returncode=$?
echo "`date +%Y-%m-%d---%r` [Info]: scp execution result: ${returncode}" | tee -a ${log_path_file};