로컬 컴퓨터에서 애플리케이션 로그를 수집한 다음 원격 컴퓨터에서 애플리케이션 로그를 수집하는 스크립트를 작성했습니다.
oldlogsdate
수집하려는 로그의 날짜를 읽는 변수가 있습니다 .
예를 들어 입력하면 Apr 23
공백이 하나뿐이므로 제대로 작동하지만 입력하면(그리고 Apr 4
사이에 공백이 두 개 있으면) 공백 하나가 제거됩니다.Apr
4
참고: 이는 oldlogsdate
사용자의 원격 컴퓨터에도 설정되며 .bash_profile
입력된 날짜는 명령을 사용하여 변경됩니다 sed
.
printf "\n";read -p "Which Date Logs you want to collect = " oldlogsdate
ssh -qt [email protected] "sed -i "s/oldlogsdate=.*/oldlogsdate=\'\"$oldlogsdate\"\'/" ~/.bash_profile"
oldlogsdate="Apr 7"
이제 이것을 사용해야 하는 이유 Apr 23
는 Apr 4
명령의 일부입니다 ls
.
읽기 명령에서 이중 공백을 유지하는 방법이 있습니까, 아니면 다른 더 좋은 방법이 있습니까?
답변1
ssh
상대방에게 보내는 명령의 일부인 명령줄에 주의하세요 .sed
ssh ... "sed -i "s/oldlogsdate=.*/oldlogsdate=\'\"$oldlogsdate\"\'/" ~/.bash_profile"
^^^^^^^^^..................................................^^^^^^^^^^^^^^^^^^
다음은 로 표시된 두 개의 인용 문자열입니다 ^
. 중간에 남아 있는 것은 다음과 같습니다.아니요변수 확장을 포함한 참조 $oldlogsdate
. 언급되지 않았으므로 적용 대상이 됩니다.분사, 및 는 Apr 7
두 단어가 Apr
되고 7
. 또한보십시오:언제 큰따옴표가 필요합니까?
이제 ssh
그것들을 다시 붙일 수 있을 만큼 똑똑해졌지만 이제 원래의 공백 크기는 사라지고 공백 하나만 추가됩니다.
이는 쉘이 공백의 원래 양을 잊어버리고 echo
단어를 단일 공백으로 묶는 방법과 다소 유사합니다.
$ echo hello world
hello world
그러나 SSH를 사용하면 SSH가 해석을 위해 명령줄을 원격 측 셸에 전달하고 해당 셸에서 단어 사이의 추가 공백도 손실되기 때문에 작은따옴표가 도움이 되지 않습니다.
그래서 이것은 여전히 작동하지 않습니다:
$ ssh localhost echo "hello world"
hello world
(로컬 셸은 따옴표를 제거하고 sum 을 ssh
가져와 위와 같이 작동하는 원격 셸에 전달합니다 .)echo
hello world
echo hello world
문자열을 그대로 유지하려면 실제로 양쪽 끝을 인용해야 합니다.
$ ssh localhost 'echo "hello world"'
hello world
printf ":%s\n" hello world
실제로 break라는 단어의 위치를 더 정확하게 표시하려면 등을 사용하는 것이 더 좋지만 결과는 비슷합니다.
큰따옴표가 가장 바깥쪽에 오도록 따옴표를 전환하여 로컬 셸에서 변수를 확장하고 원격 셸에 작은따옴표를 남겨 확장량을 최소화합니다. 다른 쪽 끝에 보내려는 큰따옴표를 백슬래시로 이스케이프해야 합니다.
$ greeting="hello world"
$ ssh localhost "echo '$greeting'"
hello world
변수 자체에 작은따옴표가 포함되어 있지 않으면 작동합니다. 그렇다면 상황이 더욱 악화됩니다. 다음을 참조하세요.다른 스크립트의 내용으로 사용하기 위해 변수를 이스케이프하세요
내 생각엔 명령줄@사샤의 답변귀하의 경우에는 효과가 있을 것 같습니다.
예를 들어 다음 질문도 참조하세요.ssh $host $FOO 및 ssh $host "sudo su user -c $FOO" 유형 구성에서 참조됩니다. 당면한 문제는더하지만 그 대답은 "더 단순한" 경우에도 적용되는 것 같습니다.
답변2
읽기 명령은 이중 공백을 제거하고 하나만 유지합니다.
그러나 실제로는 그렇지 않습니다. 명령 read
자체는 내부 공백을 변경하지 않고 그대로 둡니다(그러나 IFS
공백으로 설정하지 않는 한 앞뒤 공백을 잘라냅니다. 백슬래시를 사용하지 않으면 백슬래시도 엉망이 됩니다 -r
).
read myVar <<<'Apr 4'
echo "$myVar" # will output: Apr 4
즉, 변수 주위에 큰따옴표가 없기 때문에 공백이 손실됩니다.
myVar2='Apr 4'
echo $myVar2 # will mangle spaces, please always use "$myVar2" instead
변수를 잘못 참조하면 스크립트가 예기치 않게 작동할 뿐만 아니라 잠재적인 보안 위험이 발생할 수도 있습니다.
조금더 정확한 명령은
ssh -qt [email protected] "sed -i 's/oldlogsdate=.*/oldlogsdate=\"$oldlogsdate\"/' ~/.bash_profile"
$oldlogsdate
하지만 보편적이지 않고 값에 공백뿐만 아니라 아포스트로피, 슬래시, 백슬래시, 달러 기호, 느낌표도 포함될 수 있다는 점을 고려하지 않기 때문에 안전하지 않습니다 .