我有一个连接到 SFTP 站点并上传一些文件的期望脚本。ID 和密码包含在本地文本文件中。expect 脚本将这些文件作为变量读取,然后将其传递给 SFTP 服务器。
我遇到的问题是我们提供了复杂的密码,其中包括特殊字符($\,!)等。例如,如果密码是 pass$word,则 $ 作为特殊字符而不是文字传递。由于这是通过变量(多个站点和 ID)传递的
我无法使用“$pw”,因为它会将 $pw 直接传递给服务器,并且使用“$pw”会发送特殊字符。我需要它按原样传递密码。
到目前为止,我一直在手动将它们转义(例如 pass\$word),但这很乏味,我想以脚本方式进行。
剧本是这样的(为了保护无辜,名字和地点都改了)
#!/bin/bash
home=/data/ftp/vf/drop/
un=`cat /home/vf/workflow/.udf/.u/.u$1`
pw=`cat /home/vf/workflow/.udf/.p/.p$1`
sl=`cd /home/vf/workflow/scheduler; grep $1 upload*|cut -d \: -f1`
/usr/bin/expect -c "
spawn /usr/bin/sftp -o KexDHMin=1024 $un@$sl.mysteriouslocation.com
set timeout -1
expect *Authentication
expect Password*
send \"$pw\r\"
expect sftp*
send \"mput /$home/$1/transfer/*\r\"
expect sftp*
send \"ls \r\"
expect sftp*
send \"bye\r\"
expect eof
exit
如何将密码传递给期望脚本,以便它发送文字字符而不赋予它们特殊含义?我不认为我可以为密码文件本身编写一个“修复”脚本,这意味着进入并且每次看到一个特殊字符时,通过 sed 或其他方式将其转义,因为转义字符本身很特殊并且可能最终出现在一个循环。
非常感谢您的帮助!
将值作为环境变量传递。这也将避免命令注入漏洞并在
ps
输出中显示密码!sftp
(好吧,如果变量包含运行命令的文本,它仍然可能是命令注入漏洞!reboot
)。您可以将期望程序放在单独的脚本中(让我们称之为
sftp.expect
)并将用户名/密码作为参数传递给它。这确实存在命令行参数对系统上的其他用户可见的问题,因此这不是处理密码的最佳方法,而且您真的不想对共享系统上的密码执行此操作。
然后从shell脚本运行它
或者,如果您想将期望脚本保留在同一个 shell 脚本中,请将其粘贴在此处的文档中:
(注意 周围的引号
EOF
,我们不希望 shell 解释 heredoc 中的变量。)/[A-Za-z_0-9]/
通过使用quotemeta函数,可以使用一个小的 Perl 片段来转义(反斜杠)所有不匹配的 ASCII 字符。Perl 命令行很容易合并到您的 shell 脚本中:产生: