[英]Prevent ssh from breaking up shell script parameters
我有一個腳本,它本質上是對不同機器上同名可執行文件的包裝。 為了舉例,我將在這里包裝 printf。 我當前的腳本如下所示:
#!/bin/bash
ssh user@hostname.tld. printf "$@"
不幸的是,當 arguments 之一包含空格時,這會中斷,例如,我希望以下命令提供相同的輸出:
~$ ./wrap_printf "%s_%s" "hello world" "1"
hello_world1_
~$ printf "%s_%s" "hello world" "1"
hello world_1
當涉及(轉義的)換行符時,問題會變得更糟。 我如何在這里正確地轉義我的 arguments ?
根據 Peter Lyons 的回答,但也允許在 arguments 內引用:
#!/bin/bash
QUOTE_ARGS=''
for ARG in "$@"
do
ARG=$(printf "%q" "$ARG")
QUOTE_ARGS="${QUOTE_ARGS} $ARG"
done
ssh user@hostname.tld. "printf ${QUOTE_ARGS}"
這適用於我到目前為止測試過的所有內容,換行符除外:
$ /tmp/wrap_printf "[-%s-]" "hello'\$t\""
[-hello'$t"-]
#!/bin/sh
QUOTE_ARGS=''
for ARG in "$@"
do
QUOTE_ARGS="${QUOTE_ARGS} '${ARG}'"
done
ssh user@hostname.tld. "${QUOTE_ARGS}"
這適用於空間。 如果參數有嵌入的單引號,它就不起作用。
正確引用是非常困難的,並且在 bash 中(以一般且可靠的方式)幾乎是不可能的。
使用 Perl:
#!/usr/bin/perl
use Net::OpenSSH;
my $ssh = Net::OpenSSH->new('user@hostname');
$ssh->system('printf', @ARGV);
根據 Koert 和 Peter Lyons 的回答,這里是 ssh 的包裝器; 我稱之為“sshsystem”。 (也可在https://gist.github.com/4672115 獲得)
#!/bin/bash
# quote command in ssh call to prevent remote side from expanding any arguments
# uses bash printf %q for quoting - no idea how compatible this is with other shells.
# http://stackoverflow.com/questions/6592376/prevent-ssh-from-breaking-up-shell-script-parameters
sshargs=()
while (( $# > 0 )); do
case "$1" in
-[1246AaCfgKkMNnqsTtVvXxYy])
# simple argument
sshargs+=("$1")
shift
;;
-[bcDeFIiLlmOopRSWw])
# argument with parameter
sshargs+=("$1")
shift
if (( $# == 0 )); then
echo "missing second part of long argument" >&2
exit 99
fi
sshargs+=("$1")
shift
;;
-[bcDeFIiLlmOopRSWw]*)
# argument with parameter appended without space
sshargs+=("$1")
shift
;;
--)
# end of arguments
sshargs+=("$1")
shift
break
;;
-*)
echo "unrecognized argument: '$1'" >&2
exit 99
;;
*)
# end of arguments
break
;;
esac
done
# user@host
sshargs+=("$1")
shift
# command - quote
if (( $# > 0 )); then
# no need to make COMMAND an array - ssh will merge it anyway
COMMAND=
while (( $# > 0 )); do
arg=$(printf "%q" "$1")
COMMAND="${COMMAND} ${arg}"
shift
done
sshargs+=("${COMMAND}")
fi
exec ssh "${sshargs[@]}"
最簡單和最快的是只使用 Bash 的引用參數轉換: ${parameter@Q}
。 這可以在使用${array[@]@Q}
的數組擴展期間自動應用,但是當使用內置參數數組時,名稱和括號被刪除,因此它變成${@@Q}
。 因此,原始腳本只需要添加 4 個字符即可工作。
#!/bin/bash
ssh user@hostname.tld. printf "${@@Q}"
現在任何 escaping 都可以工作,即使是這樣的終端 colors:
./wrap_printf "%s\e[39m\e[49m\n" $'\e[30m\e[42mBlack on Green' "Just Normal Text"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.