Я нашел проблему. Проблема в символе $
. Когда я использую \\\$
как ожидаемый вывод, сценарий работает нормально. Потому что $
также является специальным символом в регулярном выражении. Когда мы используем \$
, регулярное выражение укажет это как конечный символ регулярного выражения. Поэтому нам нужно использовать \\\$
для преобразования его в \$
. Это все. Большое спасибо.
Давайте посмотрим на строку, передаваемую в /usr/linux/bin/expect -c...
; что на самом деле получает команда? Если мы заменим команду на echo
, мы увидим, что вывод дается для ожидания:
expect {
-re ".*$" {send "ls -lt cfgbackups|grep gz|head -n 1|awk '{print $9}'\r"}
}
Теперь давайте проделаем то же самое со строкой, передаваемой в send
. На этот раз мы должны использовать expect
для разбора строки, поэтому мы заменяем send
ожидаемой командой, такой какsend_user
:
expect <<\!
send_user "ls -lt cfgbackups|grep gz|head -n 1|awk '{print $9}'\r"
!
Это приводит к ошибке ожидания:
can't read "9": no such variable
Таким образом, нам нужно перестать ожидать от интерполяции $9
, используя \$9
.
Возвращаясь к исходному скрипту ksh, для создания одиночного \
в строке с двойными -кавычками нам нужно использовать \\
. Итак, наконец, исправление:
expect {
-re \".*$\" {send \"ls -lt cfgbackups|grep gz|head -n 1|awk '{print \\\$9}'\r\"}
}
Вы можете уменьшить подобные проблемы, чередуя одинарные и двойные кавычки, если между ними нет пробела. Например,:echo "hi"'there'
производит hithere
, а echo '"who'"'s"'"'
производит "who's"
. Кроме того, использование стиля <<!
и <<\!
в документах -обеспечивает другой уровень цитирования.
При смешивании ожидаемого кода со сценарием оболочки лучше всего использовать heredoc. Тогда вы избежите хотя бы одного уровня цитирования ада. В Tcl/expect регулярные выражения лучше заключать в фигурные скобки, а не в кавычки, что упрощает работу с обратными косыми чертами.
/usr/linux/bin/expect <<END_EXPECT 2>"$line".errlog &
set timeout 20
spawn ssh padmin@$line
expect {
-re {.*(P|p)assword:} {send "$2\r"}
}
expect {
-re {.*\$$} {send "ls -lt cfgbackups|grep gz|head -n 1|awk '{print \$9}'\r"}
}
expect {
-re {.*\$$} {exit 0}
eof {exit 0}
}
send_user "$expect_out(1,string)\n"
END_EXPECT
Я не уверен, следует ли писать символы новой строки и возврата каретки \r
или \\r
--, вы можете поэкспериментировать с этим.
Вы можете передавать переменные оболочки для ожидания через среду, а затем можете процитировать весь документ:
host="$line" passwd="$2" /usr/linux/bin/expect <<'END_EXPECT' 2>"$line".errlog &
#...........................................^..........^
set timeout 20
spawn ssh padmin@$env(host)
expect {
-re {.*(P|p)assword:} {send "$env(passwd)\r"}
}
expect {
-re {.*\$$} {send "ls -lt cfgbackups|grep gz|head -n 1|awk '{print \$9}'\r"}
}
expect {
-re {.*\$$} {exit 0}
eof {exit 0}
}
send_user "$expect_out(1,string)\n"
END_EXPECT
Для чего предназначена строка send_user
? Вы ничего не захватываете ни в одном шаблоне ожидания, и вы фактически выходите из ожидания в последней команде expect
. Как вы думаете, что вы там увидите?