내 컴퓨터를 로컬 서버에 백업하기 위해 bash 스크립트를 작성 중입니다. 아카이브를 압축해야 하는데 내부 ssh 명령으로 if 조건이 작동하도록 하는 방법을 찾을 수 없습니다.
if [ ssh [email protected] '$(ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l) != "0"' ]
then
ssh [email protected] "tar -czf $ARCHIVES_DIR/$YESTERDAY.tar.gz $SNAPSHOT_DIR/$YESTERDAY* \
&& rm -rf $SNAPSHOT_DIR/$YESTERDAY*"
fi
"인수가 너무 많습니다"(if 내에서) 오류가 발생합니다.
내가 뭘 잘못했나요?
답변1
구성을 단순화하고 코드를 읽는 다음 사람에게 무슨 일이 일어나고 있는지 이해할 수 있는 기회를 제공하는 것이 좋습니다. 주요 문제는 간접 실행 $( ... )
과 [ ... ]
테스트 연산자를 혼동하는 것 같다는 것입니다 . 흐름을 잘못 이해했다면 사과드립니다. 하지만 의도하신 바는 다음과 같습니다.
# Count files on the remote system and confirm that there is at least one
DATE7=$(date -v -7d '+%Y%m%d')
NFILES=$(ssh [email protected] "ls -d '/snapshots/$DATE7'* 2> /dev/null | wc -l")
# If the ssh worked and we have found files then archive them
if [ $? -eq 0 && 0 -lt $NFILES ]
then
# Archive the files
ssh [email protected] "
tar -czf '$ARCHIVES_DIR/$YESTERDAY.tar.gz' '$SNAPSHOT_DIR/$YESTERDAY'* &&
rm -rf '$SNAPSHOT_DIR/$YESTERDAY'
"
fi
이는 ARCHIVES_DIR
, SNAPSHOT_DIR
및 YESTERDAY
스크립트의 다른 곳에서 로컬로 정의된다고 가정합니다.
"..."
변수 값은 즉시 삽입 되지만 '...'
텍스트는 $WIDGET
달러 기호로 시작하는 리터럴 7자 문자열로 처리됩니다. 이 코드에 " '...' "
및 와 같은 시퀀스가 있다는 점을 고려하면 이는 주목할 가치가 있습니다 .' "..." '
답변2
명령의 반환 상태를 if 조건으로 사용할 수 있지만 올바른 구문은 괄호가 없는 것입니다. 반면에 원격 호스트에서는 대괄호나 "test" 명령을 사용해야 합니다. (나는 이것을 테스트하는 것을 선호합니다.) 이것을 시도하십시오:
if ssh [email protected] 'test $(ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l) != "0"'
then
ssh [email protected] "tar -czf $ARCHIVES_DIR/$YESTERDAY.tar.gz $SNAPSHOT_DIR/$YESTERDAY* \
&& rm -rf $SNAPSHOT_DIR/$YESTERDAY*"
fi
date 명령을 확인하고 싶을 수도 있습니다. 적어도 내 Linux 시스템에서는 date: invalid option -- 'v'
.
답변3
이 형식 if [ ... ]
은 에 대한 호출입니다 test
. 괄호로 묶인 표현식은 구문 규칙에 따라 평가되고 해석되는 test
반환 코드가 내보내집니다 . if
괄호만 제거하고 싶을 수도 있습니다.
if ssh ... | grep -q .
이 명령은 성공적인 일치 항목이 있는 경우 grep
성공적인 반환 코드("true")를 반환합니다. if
이 경우 ssh 명령의 출력이 비어 있지 않은 경우입니다. 원본 코드를 좀 더 문자 그대로 번역하면 다음과 같습니다.
if [ $(ssh ... | wc -l) != 0 ]
런타임 시 $(...)
표현식은 포함된 명령 출력의 텍스트로 대체됩니다. 즉, test
해당 정수와 0 사이의 올바른 비교가 표시됩니다.
답변4
귀하의 질문은 조건식에만 관한 것이기 때문에 if 부분만 테스트했습니다.
다음을 수행할 수 있습니다.
if [ $(ssh [email protected] 'ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l') != "0" ]
then
# do something
fi
내 대답에 약간의 추가 사항 :
행 수가 0이 아닌지 확인하는 대신 SSH 연결을 설정할 수 없다는 점을 고려해야 할 수도 있습니다.
연결이 실패하면 결과도 "0이 아님"이 되기 때문입니다.
더 나은 오류 처리를 위해 다음과 같은 것을 사용할 수 있습니다.
lines=$(ssh [email protected] 'ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l')
result=$?
# If 'ssh'-command succesful:
if [ $result == "0" ]
then
# If number of lines is non-zero:
if [ $lines != "0" ]
then
# do something
fi
else
# handle error based on $result
fi