authorized_keys
파일의 고유한 줄만 필요하므로 다음 명령의 결과를 원격 서버의 파일로 리디렉션하고 싶습니다.
ssh [email protected] awk '!seen[$0]++' /root/.ssh/authorized_keys
나는 성공하지 않고 다음을 시도했습니다.
ssh [email protected] "awk '!seen[$0]++' /root/.ssh/authorized_keys > /root/.ssh/authorized_keystemp"
ssh [email protected] "awk \'!seen[$0]++\' /root/.ssh/authorized_keys > /root/.ssh/authorized_keystemp"
ssh [email protected] '(awk \'!seen[$0]++\' /root/.ssh/authorized_keys > /root/.ssh/authorized_keystemp)'
내 Google이 실패하고 있습니다. 내가 뭘 잘못하고 있는지 알 수 있나요?
답변1
이것을 시도해 보십시오(내 컴퓨터에서 테스트했는데 제대로 작동하는 것 같습니다. 제거할 중복 항목은 없지만...).
ssh [email protected] "awk '!seen[\$0]++' /root/.ssh/authorized_keys > /root/.ssh/authorized_keystemp"
"
에 백슬래시가 없어 -quote 시도가 작동하지 않아 과 $
같이 $0
확장됩니다 bash
.
작은 따옴표를 사용한 시도는 'foo\'some thing\'foo'
당신이 생각하는 것을 의미하지 않기 때문에 작동하지 않습니다. \
- 이스케이프 문자는 작은따옴표로 묶인 문자열 내에서 해석되지 않습니다. 따라서 이것은 실제로 불균형 따옴표와 두 개의 인수입니다. 첫 번째는 이고 foo\some
두 번째는 이지만 마지막 인수는 작은 따옴표로 묶인 새 문자열을 시작하기 thing'foo
때문에 불완전합니다 .'
쉘 탈출은 고통스러울 수 있으며, 특히 이중 탈출은 더욱 그렇습니다. 셸 스크립트를 먼저 보낸 다음( 등을 사용하여) 실행하는 것이 sftp
더 scp
쉬운 경우가 많습니다 .
답변2
필요한 정보를 제공하는 DeRobert의 답변을 수락하겠습니다. 여전히 문제가 있었고 그것이 내 awk
명령일지도 모른다고 생각하고 다른 방법으로 교체했습니다. 원격 서버의authorized_keys 파일에 고유한 항목만 포함되도록 하기 위해 제가 수행한 작업은 다음과 같습니다.
ssh [email protected] "sort /root/.ssh/authorized_keys | uniq > /root/.ssh/temp"
ssh [email protected] "mv -f /root/.ssh/temp /root/.ssh/authorized_keys"
답변3
쉘 확장 및 토큰화로부터 보호하기 위해 무언가를 인용하는 것에 대해 알아야 할 모든 것은 다음과 같습니다.
- 아포스트로피 사이에 아포스트로피를 제외한 모든 항목을 묶습니다. 예를 들어,
do not
가 됩니다'do not'
. - 아포스트로피를 이스케이프하려면 백슬래시를 사용
'
하세요\'
. - 문자열을 아포스트로피와 기타 문자로 나누고 이전 2개의 규칙을 적용한 후 결과를 연결합니다. 예를 들어,
don't
가 됩니다'don'\''t'
.
이러한 일반 규칙을 적용하면 다음과 같이 질문의 명령을 올바르게 인용할 수 있습니다.
ssh [email protected] 'awk '\''!seen[$0]++'\'' /root/.ssh/authorized_keys > /root/.ssh/authorized_keystemp'
동일한 문자열을 참조하는 더 읽기 쉬운 방법이 있지만 이 방법은 일반적으로 적용 가능하며 올바른지 시각적으로 쉽게 확인할 수 있습니다.
나는 이 작업을 너무 자주 수행하기 때문에 이를 수행하기 위한 쉘 함수/스크립트를 작성했고 항상 그것을 사용했습니다. 여기있어:
#!/bin/sh -
# shellquote foo => foo
# shellquote foo&bar => 'foo&bar'
# shellquote foo'bar => 'foo'\''bar'
shellquote() {
local input="$1"
local output=""
local backslash='\'
local apostrophe="'"
if [ -z "${input}" ]; then
# Empty string => pair of apostrophes
output="''"
fi
while [ -n "${input}" ]; do
case "${input}" in
"'"*)
# Escape the apostrophe.
output="${output}${backslash}${apostrophe}"
input="${input#${apostrophe}}"
;;
*"'"*)
# Quote everything before the first apostrophe, and then escape
# the apostrophe.
output="${output}${apostrophe}${input%%${apostrophe}*}${apostrophe}${backslash}${apostrophe}"
input="${input#*${apostrophe}}"
;;
*[!+,./0-9:=@A-Z_a-z-]*)
# There are no apostrophes, but at least one character needs quoting.
# So quote the entire word.
output="${output}${apostrophe}${input}${apostrophe}"
input=""
;;
*)
# Nothing needs quoting. Output everything literally.
output="${output}${input}"
input=""
esac
done
printf '%s' "${output}"
}
main() {
local sep=''
for arg; do
printf '%s' "${sep}"
shellquote "${arg}"
sep=' '
done
}
main "$@"