像这样:
echo $USER $PASSWORD $RESOURCE_MACHINE $SELECT_SQL $TARGET_MACHINE $INSERT_SQL | xargs -n6 bash -c '/usr/bin/clickhouse-client -u $1 --password $2 -h $3 -q $4 | /usr/bin/clickhouse-client -u $1 --password $2 -h $5 -q $6' bash
每个参数都是一个字符串。
答案1
xargs
' 输入需要以非常特定的格式进行格式化。要成为参数的字符串需要用 SPC、TAB、NL(可能还有其他空白字符,具体取决于实现xargs
和区域设置)分隔,如果这些字符中的任何一个可能出现在字符串中,则需要用单引号将它们引起来引号、双引号或反斜杠(NL 除外,只能用反斜杠转义)。
反斜杠和引号也需要转义。并且空元素必须用引号引起来,以免被丢弃。
所以在这里,你不能使用echo
来以 识别的格式输出单词列表xargs
。更一般地说,echo
无论如何都不能用于输出任意数据,因为它自己处理反斜杠和/或以-
.
在这里,使用bash
,您可以定义:
print-for-xargs() {
local nl=$'\n'
if (($# > 0)); then
set -- "${@//\'/\'\\\'\'}"
printf "'%s'\n" "${@//$nl/\'\\$nl\'}"
fi
}
该函数以预期的格式打印其参数xargs
(将每个参数放在单引号内,单引号和换行符本身用反斜杠引用外部单引号字符串)。
然后,你可以这样做:
print-for-xargs "$USER" \
"$PASSWORD" \
"$RESOURCE_MACHINE" \
"$SELECT_SQL" \
"$TARGET_MACHINE" \
"$INSERT_SQL" |
xargs -n6 bash -c '
/usr/bin/clickhouse-client -u "$1" --password "$2" -h "$3" -q "$4" |
/usr/bin/clickhouse-client -u "$1" --password "$2" -h "$5" -q "$6"
' bash
还要记住,参数扩展必须bash
像大多数其他类似 POSIX 的 shell 中一样加引号。
如果您xargs
支持非标准-0
选项(对于输入上的 NUL 分隔记录,0 是唯一不能出现在命令参数中的字节值),则可以大大简化为:
print_for_xargs0() {
[ "$#" -eq 0 ] || printf '%s\0' "$@"
}
print_for_xargs0 "$USER" \
"$PASSWORD" \
"$RESOURCE_MACHINE" \
"$SELECT_SQL" \
"$TARGET_MACHINE" \
"$INSERT_SQL" |
xargs -0 -n6 sh -c '
/usr/bin/clickhouse-client -u "$1" --password "$2" -h "$3" -q "$4" |
/usr/bin/clickhouse-client -u "$1" --password "$2" -h "$5" -q "$6"
' sh
(不需要bash
那里,标准sh
也可以)
假设您确实需要xargs
出于某种原因致电,并且您只是显示一个简化的示例。
在这里,你可以这样做:
bash -c '
/usr/bin/clickhouse-client -u "$1" --password "$2" -h "$3" -q "$4" |
/usr/bin/clickhouse-client -u "$1" --password "$2" -h "$5" -q "$6"
' bash "$USER" "$PASSWORD" "$RESOURCE_MACHINE" "$SELECT_SQL" \
"$TARGET_MACHINE" "$INSERT_SQL"
xargs
根本不调用或者:
/usr/bin/clickhouse-client -u "$USER" --password "$PASSWORD" \
-h "$RESOURCE_MACHINE" -q "$SELECT_SQL" |
/usr/bin/clickhouse-client -u "$USER" --password "$PASSWORD" \
-h "$TARGET_MACHINE" -q "$INSERT_SQL"
无需运行解释器的单独实例bash
。
另请注意,在所有这些示例中, 的值最终出现在传递给(以及运行 的参数)$PASSWORD
的参数中,这是不好的做法,因为命令参数是系统本地的公共知识(它们显示在 的输出中, 并且可能最终出现在审核日志中)。clickhouse-client
bash
bash
ps -f
答案2
如果您被允许使用 GNU Parallel:
echo "$USER $PASSWORD $RESOURCE_MACHINE $SELECT_SQL $TARGET_MACHINE $INSERT_SQL" |
parallel --colsep ' ' /usr/bin/clickhouse-client -u {1} --password {2} -h {3} -q {4} '|' /usr/bin/clickhouse-client -u {1} --password {2} -h {5} -q {6}
我们假设变量中没有空格。
如果变量中有空格,请选择一个未出现的字符串(例如 :::)并使用它:
echo "$USER:::$PASSWORD:::$RESOURCE_MACHINE:::$SELECT_SQL $TARGET_MACHINE:::$INSERT_SQL" |
parallel --colsep ':::' /usr/bin/clickhouse-client -u {1} --password {2} -h {3} -q {4} '|' /usr/bin/clickhouse-client -u {1} --password {2} -h {5} -q {6}
但在您的特定情况下,这似乎是多余的,因为您可以直接在命令中使用变量。
/usr/bin/clickhouse-client -u "$USER" --password "$PASSWORD" -h "$RESOURCE_MACHINE" -q "$SELECT_SQL" |
/usr/bin/clickhouse-client -u "$USER" --password "$PASSWORD" -h "$TARGET_MACHINE" -q "$INSERT_SQL"