为了开始分布式计算,我编写了一个运行脚本,它使用ssh登录到一台远程计算机,并启动一个从标准输入读取的脚本.但是,此运行脚本需要将用户提供的参数从$@正确传输到远程计算机.然而,我注意到这些论点没有被正确传达.

假设远程机器应该执行的脚本task.sh

i=0
for p in "$@"; do
  echo "#${i}: ${p}"
  i=$((i+1))
done

此脚本简单地迭代参数并逐行打印它们,例如,

$ bash task.sh hello world 'in one line'
#0: hello
#1: world
#2: in one line

我的简化运行脚本run.sh现在如下所示:

ssh user@remote.example.com "bash -s $@" < task.sh

但是,这将打印以下内容:

$ bash run.sh hello world 'in one line'
#0: hello
#1: world
#2: in
#3: one
#4: line

当我引用$@',即.

ssh user@remote.example.com "bash -s '$@'" < task.sh

打印的内容如下:

$ bash run.sh hello world 'in one line'
#0: hello world in one line

也许,当我在run.sh中使用一个数组时,它是有效的?

ARGS=(bash -s "$@")
ssh user@remote.example.com "${ARGS[@]}" < task.sh

不,它还可以打印多行'in one line'.

${ARGS[@]}左右添加额外的单引号会使ssh将其解释为单个命令和报告:bash: bash -s hello world in one line: command not found.

那么,如何正确地将参数传递给ssh,以便正确地拆分它们呢?我想,它可能可以与环境变量一起工作,但我也可以让它在没有环境变量的情况下工作吗?

推荐答案

您需要将带双引号的"$@"传递给远程shell .要防止本地shell 程序将其展开,请在双引号两边使用单引号.(原文如此.)

ssh user@remote.example.com bash -s '"$@"' < task.sh

或等同于

ssh user@remote.example.com 'bash -s "$@"' < task.sh

数组try 只会把事情推来推go ,不会改变任何事情;尽管如果使用得当,数组确实可以帮助解决这类问题.

args=(bash -s '"$@"')
ssh user@remote.example.com "${args[@]}" < task.sh

另见Correct Bash and shell script variable capitalization

更复杂的是,您还需要对远程shell的参数进行双重引用.一层由本地shell剥离,另一层由远程shell剥离.

ssh user@remote.example.com 'bash -s "$@"' < task.sh hello world '"in one line"'

更自然的解决方案是使用数组在包装器中应用额外的引号.

#!/bin/bash
args=()
for arg; do
   args+=($(printf '%q' "$arg"))
done
ssh user@remote.example.com bash -s "${args[@]}" <<\____
    i=0
    for p in "$@"; do
      echo "#${i}: ${p}"
      i=$((i+1))
    done
____

在HAT TIP为How do I pass subshell results (array) to an SSH command?的情况下,我还使用了内联task.sh作为run.sh的一部分.

最初的伯恩shell 只有$*个,就是因为这个问题.修复方法是引入$@,这与显式调用时使用双引号时的only有所不同.这是Bourne legacy.号公交车的一个非常隐蔽的角落案件

Linux相关问答推荐

BASH-SCRIPT-在特定行合并两个文件

使用信号处理程序实现Hibernate 功能

使用ms宏将PIC图像放置在页面的任意位置

条件句if的正确写法是怎样的?

如何在不进行轮询且不吃掉其他人子进程的退出代码的情况下等待一组子进程(并且只有它们)?

Linux PREEMPT_RT:SCHED_OTHER 的性能优于 SCHED_FIFO.为什么?

使用正则表达式捕获特定字符串

使用 AWK 过滤 Linux 输出

命令应在终端关闭后继续运行

从 bash shell 等效项在fish shell 上设置 $ANDROID_SDK_ROOT

如何从linux调度程序中屏蔽一个cpu(防止它调度线程到那个cpu上)?

在三星 chromebook 上编程

如何在 Linux 上捕获原始 HID 输入?

如何使用该位置的相对路径在单个位置创建多个文件夹?

隐藏文件 .env 未使用 Docker COPY 复制

使用 C/C++ (GCC/G++) 在 Linux 中的套接字编程中发送和接收文件

如何分析内存使用情况?

命令行 Arduino 编译和上传?

Anaconda 安装后,conda 命令失败并显示ImportError: no module named conda.cli

在 Docker 容器中运行的 JVM 的驻留集大小 (RSS) 和 Java 总提交内存 (NMT) 之间的差异