我试图通过在我的一个函数(包含在 .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
值传递给远程 shellLC_FILE_NAME
(假设sshd
远程主机上配置了AcceptEnv LC_*
通用的)。在您的代码中,您让远程 shell 扩展了一个$FILE
变量(尽管忘记了引用它以及*
),但是您没有将该变量从本地 shell 传递到远程 shell。 $REPLY
for scalar 和$reply
for array 是变量名的常见约定,我们将结果返回给调用者。- 您不能用于
echo
任意数据(对于您无法保证不包含反斜杠或以 开头的数据-
)。 -name '*foo*'
foo
可能无法使用多字节字符集(例如 UTF-8)匹配其名称中的所有文件,因为无法将文件名解码为该字符集会导致sfnmatch()
使用的错误。因此修复为单字节语言环境。find
-name
LC_ALL=C
- 在这里,我们将返回失败退出状态,除非至少找到一个文件并且已正确打印。
- 我们使用
-n
选项来ssh
避免它消耗来自标准输入的输入。您可能还想添加一个-o BatchMode=yes
与无人值守处理相关的更多调整。
更多阅读内容请参见此处:
答案2
您可以重新路由stderr
以stdout
使用
OUT=$(ssh -tt -vv [email protected] "remote command" 2>&1 )
您可以在函数中编辑类似的内容,它应该可以工作!