问题描述
我的脚本外壳:
remotepass="12345"
echo
echo "list files ssh"
echo "=========="
listDoc=$(ssh user@111.111.111.111 ls /data/dcrm_int/ftp/out/rpt/dwh/20200820/*DWH_CRM_SYS_OPERLOG_20200820*)
echo $listDoc
echo
echo "list files"
echo "=========="
for document in $listDoc; do
echo $document
done
cat > expect_1.dat << EOF
spawn ssh user@111.111.111.111 ls /data/dcrm_int/ftp/out/rpt/dwh/20200820/*DWH_CRM_SYS_OPERLOG_20200820*
expect "*?assword*"
send "$remotepass\r"
interact
EOF
listDoc=$(expect "expect_1.dat")
echo
echo "result"
echo "======"
echo $listDoc
echo
echo "list files"
echo "=========="
for document in $listDoc; do
echo $document
done
我希望得到的结果就像第一个红色方框
解决方法
默认情况下,spawn
回显所有已发送的内容和已接收的内容。
您可以通过将其添加到期望的脚本开始中来禁用它:
log_user 0
这将删除不需要的起始文本。
一个看不见的问题是输出在每行末尾包含回车符 control-M 。您可以这样做
echo "$listDoc"|cat -v
每行将以^M
结尾。这是因为spawn使用的pty将继承当前的stty设置,其中包括onlcr
,即将输出换行换成回车换行。您可以通过几种方式删除这些字符,但也可以通过将其添加到期望脚本开始中来避免它们:
set stty_init -onlcr
另一个问题是输出以空行开头。您可以通过添加
来避免这种情况expect "\n"
就在interact
之前。
确保在外壳程序中双引号:
echo "$listDoc"
,
一个外壳技巧,使用bash,将输出的行读入数组:
mapfile -t listDoc < <(expect "expect_1.dat")
然后
echo
echo "list files"
echo "=========="
for document in "${listDoc[@]}"; do
echo "$document"
done
阅读Security implications of forgetting to quote a variable in bash/POSIX shells
列出meuh的建议:
cat > expect_1.dat << EOF
log_user 0
set stty_init -onlcr
spawn ssh user@111.111.111.111 ls /data/dcrm_int/ftp/out/rpt/dwh/20200820/*DWH_CRM_SYS_OPERLOG_20200820*
expect "*?assword*"
send "$remotepass\r"
log_user 1
expect eof
EOF
引号heredoc通常是一个好主意,特别是如果您将在Expect中使用更多代码并使用Expect变量的话。然后,您可以通过环境传递外壳变量以期望:
export remotepass
# note the quotes in the next line: the whole heredoc is a single quoted string
cat > expect_1.dat << 'EOF'
log_user 0
set stty_init -onlcr
spawn ssh user@111.111.111.111 ls /data/dcrm_int/ftp/out/rpt/dwh/20200820/*DWH_CRM_SYS_OPERLOG_20200820*
expect "*?assword*"
send "$env(remotepass)\r" # using the environment variable
log_user 1
expect eof
EOF