ssh USER@HOST -p PORT $(printf "%q" "cmd") $(printf "%q" "arg1") \
$(printf "%q" "arg2")
Для более детального решения прочтите комментарии и просмотрите другой ответ .
Что ж, мое решение не будет работать с оболочками, отличными от bash
. Но если предположить, что с другой стороны это bash
, все станет проще. Моя идея состоит в том, чтобы повторно использовать printf "% q"
для экранирования. Также, как правило, удобнее иметь на другом конце сценарий, принимающий аргументы. Но если команда короткая, возможно, ее можно встроить. Вот несколько примеров функций для использования в сценариях:
local.sh
:
#!/usr/bin/env bash
set -eu
ssh_run() {
local user_host_port=($(echo "$1" | tr '@:' ' '))
local user=${user_host_port[0]}
local host=${user_host_port[1]}
local port=${user_host_port[2]-22}
shift 1
local cmd=("$@")
local a qcmd=()
for a in ${cmd[@]+"${cmd[@]}"}; do
qcmd+=("$(printf "%q" "$a")")
done
ssh "$user"@"$host" -p "$port" ${qcmd[@]+"${qcmd[@]}"}
}
ssh_cmd() {
local user_host_port=$1
local cmd=$2
shift 2
local args=("$@")
ssh_run "$user_host_port" bash -lc "$cmd" - ${args[@]+"${args[@]}"}
}
ssh_run USER@HOST ./remote.sh "1 ' \" 2" '3 '\'' " 4'
ssh_cmd USER@HOST:22 "for a; do echo \"'\$a'\"; done" "1 ' \" 2" '3 '\'' " 4'
ssh_cmd USER@HOST:22 'for a; do echo "$a"; done' '1 "2' "3' 4"
remote.sh
:
#!/usr/bin/env bash
set -eu
for a; do
echo "'$a'"
done
Вывод:
'1 ' " 2'
'3 ' " 4'
'1 ' " 2'
'3 ' " 4'
1 "2
3' 4
В качестве альтернативы вы можете выполнить printf
сами, если знаете, что делаете:
ssh USER@HOST ./1.sh '"1 '\'' \" 2"' '"3 '\'' \" 4"'