我在 Bash 脚本中有这样的逻辑:
运行一些东西;
如果失败,请打印某些内容并停止;
如果没有,请运行其他内容。
所有这些都在ssh
会话中运行。
如果我使用$?
和if / else
,这可能是微不足道的。 但是由于脚本的可维护性,我正在寻找一些优雅的 2 行解决方案。
这就是我到目前为止所拥有的
ssh ... '
ls attributes/*'$CONF_FILE'.rb || ls -l attributes/ && exit 1;
'$EDITOR' attributes/*'$CONF_FILE'.rb '$PART_VER';'
但是,无论如何,这都会退出。所以我尝试了:
ssh ... '
ls attributes/*'$CONF_FILE'.rb || (ls -l attributes/ && exit 1);
'$EDITOR' attributes/*'$CONF_FILE'.rb '$PART_VER';'
但是,exit
仅退出子外壳。从子外壳中退出脚本一点也不优雅。
有没有简单的 2 线解决方案?也许其他运算符优先?
为清晰、正确和可维护性而编写 -而不是简洁:
# store your remote script as a string. Because of the quoted heredoc, no variables are
# evaluated at this time; $1, $2 and $3 are expanded only after the code is sent to the
# remote system.
script_text=$(cat <<'EOF'
CONF_FILE=$1; PART_VER=$2; EDITOR=$3
shopt -s nullglob # Return an empty list for any failed glob
set -- attributes/*"$CONF_FILE".rb # Replace our argument list with a glob result
if (( $# )); then # Check length of that result...
"$EDITOR" "$@" "$PART_VER" # ...if it's nonzero, run the editor w/ that list
else
ls attributes # otherwise, run ls and fail
exit 1
fi
EOF
)
# generate a single string to pass to the remote shell which passes the script text
# ...and the arguments to place in $0, $1, etc while that script is running
printf -v ssh_cmd_str '%q '
bash -c "$script_text" '_' "$CONF_FILE" "$PART_VER" "$EDITOR"
# ...thereafter, that command can be run as follows:
ssh -tt ... "$ssh_cmd_str"
不要使用子外壳;使用命令组。
ssh ... "
ls attributes/*'$CONF_FILE'.rb || { ls -l attributes/ && exit 1; };
'$EDITOR' attributes/*'$CONF_FILE'.rb '$PART_VER';"
(请注意引号的变化;这更好地确保本地参数扩展的结果在远程端正确引用,尽管如果参数扩展本身包含单引号,仍然存在问题。正确的解决方案是在远程端运行显式 shell,将本地参数作为参数,而不是使用插值来构建脚本。以下内容未经测试,但我认为我正确引用了所有内容。
ssh ... sh -c '
ls attributes/*"$1.rb" || { ls -l attributes/ && exit 1; };
"$EDITOR" attributes/*"$1.rb" "$2";
' _ "$CONF_FILE" "$PART_VER"
(
现在,我诉诸于复制条件,如下所示:
ssh ... '
ls attributes/*'$CONF_FILE'.rb > /dev/null || ls -l --color=always attributes/
ls attributes/*'$CONF_FILE'.rb > /dev/null || exit 1;
'$EDITOR' attributes/*'$CONF_FILE'.rb '$PART_VER';'
(我使用&>-
作为将 stdout 和 stderr 重定向到/dev/null
的缩写,但这可能不正确,请参阅评论。