SSH 및 sudo를 사용할 때 쉘에서 따옴표를 이스케이프 처리하는 방법은 무엇입니까?

SSH 및 sudo를 사용할 때 쉘에서 따옴표를 이스케이프 처리하는 방법은 무엇입니까?

전체적으로 :

질문과 예시는 로컬에서 테스트할 수 있습니다.

sh -c "echo 'how to print single quote here'"

세부 사항:

다음과 같은 구성이 있습니다.

upload_server = ('192.168.1.1', 10051)

이제 서버 구성을 대체하려면 쉘 스크립트가 필요합니다. 로컬에서는 sed를 사용하여 다음을 수행할 수 있습니다.

sed -E 's/(    upload_server = ).*/\\1('\"'$a'\"', 10051)/g' config.py

그러나 구성을 변경해야 하는 시스템이 많이 있습니다.

올바른 계획은 sshfor..in과 함께 사용하는 것입니다.

for i in `cat hosts`; do ssh $i "cmd"; done

그러나 구성을 변경하려면 하나가 더 필요합니다 sudo. 다음과 같습니다.

for i in `cat hosts`; do ssh $i "sudo -c \"cmd\""; done

이제 sed에서:

upload_server=123.123.123.123
upload_server_port=1000
cmd="sed -E 's/(    upload_server = ).*/\\1('\"\"'\"'${upload_server}'\"'\"\"', ${upload_server_port})/g' config.py"
ssh $i "sudo -c \"${cmd}\""

구성 결과:

upload_server = (123.123.123.123, 1000)

다음과 같아야 합니다.

upload_server = ('123.123.123.123', 1000)

이제 따옴표 사용법에 대해 혼란스러워졌습니다. :(

답변1

이 경우 표준 입력에 sed 스크립트를 전달하면 인용 문제를 완전히 우회할 수 있습니다. SSH는 로컬 표준 입력을 원격 프로세스로 라우팅하고 sudo는 이를 열어두고 sed는 stdin에서 스크립트를 읽을 수 있습니다. 다음을 사용하여 표준 입력의 내용을 전달할 수 있습니다.여기 문서.

for i in `cat hosts`; do
  ssh "$i" 'sudo sed -f - …' <<'EOF'
s/(    upload_server = ).*/\1("$a", 10051)/g
EOF
done

보다 일반적으로 stdin에 데이터를 전달할 필요가 없는 한, 인용에 대한 걱정 없이 SSH를 통해 stdin의 쉘 조각을 전달할 수 있습니다.

for i in `cat hosts`; do
  ssh "$i" sudo sh <<'EOF'
sed 's/(    upload_server = ).*/\1("$a", 10051)/g' …
EOF
done

"$a"구성 파일을 삽입하려는지 또는 "something"변수 값이 로컬 셸에 있는 위치가 귀하의 질문에서 명확하지 않습니다. 지역 변수를 참조하려면 here 문서를 보간법과 함께 사용하고 here 문서에서 백슬래시로 보호하세요. sed와 두 번째 코드 조각의 원격 셸에 의한 구문 분석으로 인해 변수 값에는 문자나 줄바꿈이 포함되어서는 안 됩니다.asomething$\`\/'

  ssh "$i" sudo sh <<EOF
sed 's/(    upload_server = ).*/\\1("$a", 10051)/g' …
EOF

답변2

$ ssh localhost sh -c \"echo \\\'how to print single quotes here\\\'\"
'how to print single quotes here'

$ ssh localhost echo \\\'how to print single quotes here\\\'
'how to print single quotes here'

이러한 규칙을 이해하려면 로컬 셸이 첫 번째 수준 참조를 제거한 다음 SSH가 원격 셸을 호출하여 두 번째 수준 참조를 제거한다는 점을 기억하세요.

관련 정보