如何在函数中运行 SSH 命令并将输出存储在变量中?

如何在函数中运行 SSH 命令并将输出存储在变量中?

我试图通过在我的一个函数(包含在 .bashrc 中)中运行以下命令来查找(并存储到变量)存储在另一台服务器上的文件的路径:

FILE_PATH=$(ssh -T user@host 'find <directory> -name *<filename>*')

但是,这不会返回任何输出。我已经检查过在抓取的位置应该有一个文件,并且我还能够复制命令并将输出存储到命令行上的变量,但在运行该函数时它不起作用。

有谁知道发生了什么事以及为什么命令不起作用?

编辑:

这是我所看到的内容的表示:

function get_path {
    FILE=$1
    FILE_PATH=$(ssh -T user@hostB 'find /home/daverbuj -name *${FILE}*')
    echo "Here is the file: ${FILE_PATH}"
}
[daverbuj@hostA]$ FILE_A=$(ssh -T user@hostB 'find /home/daverbuj -name foo.bar')
[daverbuj@hostA]$ echo $FILE_A
/home/daverbuj/foo.bar

[daverbuj@hostA]$ get_path foo.bar
Here is the file:

当我从命令行运行时,我看到了我所期望的结果,但当我运行该函数时却没有看到。

答案1

get_path() {
  local name=$1
  readarray -td '' reply < <(
    LC_FILE_NAME=$name ssh -o SendEnv=LC_FILE_NAME -n -T user@hostB '
      LC_ALL=C find /home/daverbuj -name "*$LC_FILE_NAME*" -print0')
  (( ${#reply[@]} )) &&
    echo "File path${reply[2]+s} with that name:" &&
    printf ' - %s\n' "${reply[@]}"
}
  • 无需使用ksh风格的函数定义(function f {...}),也bash支持标准。f() compound-command
  • 可能有多个匹配文件。为了可靠地将它们分开,您需要使用 NUL 作为分隔符 ( -print0)。bash变量不能保存 NUL,但从版本 4.4 开始,它的readarray内置函数可以将 NUL 分隔的输入流拆分为带有-d ''.
  • *是一个全局运算符,因此需要为本地 shell 和远程 shell 引用它,以便将其逐字传递给find-name名称模式匹配运算符。
  • 您不希望本地 shell 将变量扩展为传递到远程 shell 的代码,因为这会构成某种形式的任意命令注入漏洞,相反,我们在这里通过环境变量将该$name值传递给远程 shell LC_FILE_NAME(假设sshd远程主机上配置了AcceptEnv LC_*通用的)。在您的代码中,您让远程 shell 扩展了一个$FILE变量(尽管忘记了引用它以及*),但是您没有将该变量从本地 shell 传递到远程 shell。
  • $REPLYfor scalar 和$replyfor array 是变量名的常见约定,我们将结果返回给调用者。
  • 您不能用于echo任意数据(对于您无法保证不包含反斜杠或以 开头的数据-)。
  • -name '*foo*'foo可能无法使用多字节字符集(例如 UTF-8)匹配其名称中的所有文件,因为无法将文件名解码为该字符集会导致sfnmatch()使用的错误。因此修复为单字节语言环境。find-nameLC_ALL=C
  • 在这里,我们将返回失败退出状态,除非至少找到一个文件并且已正确打印。
  • 我们使用-n选项来ssh避免它消耗来自标准输入的输入。您可能还想添加一个-o BatchMode=yes与无人值守处理相关的更多调整。

更多阅读内容请参见此处:

答案2

您可以重新路由stderrstdout使用

OUT=$(ssh -tt -vv [email protected] "remote command" 2>&1 )

您可以在函数中编辑类似的内容,它应该可以工作!

相关内容