Закрытие соединения через s_client в скрипте оболочки
Я пытаюсь установить соединение с сервером IMAP в сценарии оболочки. Несмотря на то, что я могу подключиться и выполнить команды, надлежащим образом закрытие соединения кажется невозможным.
Это тестовая команда, которую я использую:
openssl s_client -crlf -connect server:993 <<EOF
01 login USERNAME PASSWORD
02 LIST "" "*"
03 logout
EOF
Поскольку соединение закрывается, как только заканчивается вход, это происходит до того, как какой-либо вывод получен, поэтому я никогда не получаю требуемые данные.
Если я добавлю опцию -ign_eof
опция, так что он будет игнорировать окончание ввода, чтобы сохранить соединение открытым, выход возвращается по желанию. Но вместо этого после того, как соединение было закрыто...
* BYE Logging out
03 OK Logout completed.
... s_client остается живым, поэтому выполнение никогда не возвращается к сценарию.
Есть ли решение, которое заставит s_client завершать работу, когда сервер закрывает соединение?
Или есть альтернативный метод с использованием стандартных инструментов? Скрипт будет работать на Mac OS X, Debian, а также на производном от Redhat и, возможно, на эмуляторе терминала Android, поэтому я хотел бы использовать довольно стандартные инструменты для переносимости, а не специализированные пакеты.
Обновление: я пришел с ответом, который меня не совсем устраивает, но который работает. Он использует скрипт для передачи команд в openssl, но затем вводит бесконечный цикл, чтобы держать stdin открытым, пока не получит сигнал, чтобы он сказал, что нужно выйти. Вот мой тестовый скрипт:
#!/bin/sh
if [ "$1" = "doit" ]; then
trap "echo \"04 logout\"; exit" SIGUSR1
echo "00 login USERNAME PASSWORD"
echo "01 SELECT PID-$$"
echo "02 SELECT FOLDER"
echo "03 FETCH 1:* (BODY[HEADER.FIELDS (Subject)])"
while :; do :; done
fi
MYFLAG=
$0 doit | openssl s_client -crlf -connect server:993 2>/dev/null | while read LINE; do
LINE=`echo "$LINE" | tr -d '\r'`
[ "${LINE:0:4}" = "* OK" ] && MYFLAG=Y
[ "${LINE:0:33}" = "01 NO Mailbox doesn't exist: PID-" ] && PID="${LINE##*PID-}"
[ "$MYFLAG" ] && echo "$LINE"
[ "$PID" -a "$LINE" = "03 OK Fetch completed." ] && kill -USR1 $PID
done
echo "Finished."
Сценарий вызывает себя с параметром для вывода команд IMAP, которые передаются в openssl, чей вывод передается в read
цикл, чтобы он мог быть обработан. Переменная MYFLAG просто используется, чтобы скрыть информацию, выводимую openssl, и просто отображать вывод из соединения с сервером.
Я выбираю фиктивное имя папки, которое включает в себя PID второго экземпляра скрипта, чтобы передать его обратно, очевидно, что временный файл был бы лучше, но для тестирования я хотел сохранить все самодостаточным и иметь возможность наблюдать за тем, что происходило.
Как только информация о выборке отображена, и сервер возвращает ответ OK, он отправляет сигнал SIGUSR1 во второй экземпляр сценария, который затем отправляет сообщение о выходе из системы и завершает работу, закрывая stdin, что приводит к отключению s_client.
Первоначально я включил 04 logout
команда в начальном наборе echos, но когда я сделал это, цикл чтения отображался только до тех пор, пока вывод выборки не остановился, он даже не показывал состояние OK для операции, хотя все было получено.
Также мне нужно использовать tr
для удаления завершающих возвратов каретки, но если я передаю вывод из openssl, то цикл чтения ничего не получит.
1 ответ
Вы можете исправить это, синхронизировав ваш ввод с openssl. самый простой способ, которым я могу придумать, это использовать функцию, которая выводит ввод в стандартный вывод:
#!/bin/sh
imapscript () {
echo '01 login USER PASSWD'
echo '02 LIST "" "*"'
echo '03 logout'
while sleep 1; do
echo "04 logout"
done
}
imapscript | openssl s_client -crlf -connect server:993