У меня есть сервер с 2fa и не позволяет войти в систему с помощью ключей ssh. Я хочу подключиться через FTP, я использую sshfs.
Обычный sshfs user@host:/remote/ /local/ работает нормально. Но я хотел передать пароль с помощью expect (-o password_stdin у меня не работает).
Я определил функцию в .bashrc
function mount_sshfs_with_2fa() {
# Get the FTP password from the encrypted file
local password=$(gpg --decrypt encrypted_password.txt)
# Prompt for verification code
read -p "Verification code: " otp
echo $otp
expect << EOF
spawn sshfs user@host:/remote/ /local/
expect -re "code:"
send -- "$otp\r"
send_user "Verification code: $otp\n"
expect -re "Password:"
send -- "$password\r"
send_user "Password: $password\n"
EOF
}
Ошибки не выдает, но и не монтируется. Пожалуйста, скажите мне, что случилось.
отлаживать
expect -d дает
Verification code: 325776
325776
expect version 5.45.4
argv[0] = expect argv[1] = -d
set argc 0
set argv0 "expect"
set argv ""
executing commands from command file
spawn sshfs user@host:/remote/ /local/
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {153497}
expect: does "" (spawn_id exp4) match glob pattern "code:"? no
Verification code:
expect: does "\rVerification code: " (spawn_id exp4) match glob pattern "code:"? yes
expect: set expect_out(0,string) "code:"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "\rVerification code:"
send: sending "325776\r" to { exp4 }
expect: does " " (spawn_id exp4) match glob pattern "assword:"? no
expect: does " \r\n" (spawn_id exp4) match glob pattern "assword:"? no
Password:
expect: does " \r\n\rPassword: " (spawn_id exp4) match glob pattern "assword:"? yes
expect: set expect_out(0,string) "assword:"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) " \r\n\rPassword:"
send: sending "(my password)\r" to { exp4 }
обновление 2 Вместо здесь-кода также не работает следующее
expect -c "
spawn sshfs user@host:/remote/ /local/
expect "code:"
send -- "$otp\r"
expect "assword:"
send -- "$password\r"
interact
"
expect это что-то серьезное или просто пустая трата времени? Я видел несколько решений, которые работали для других, и у меня возникла ошибка! Например, interact не работает внутри expect здесь-кода?
С таким же успехом вы можете не использовать -p для чтения одноразового пароля, если вы собираетесь распечатать его на следующем шаге.
нет, я следил за тем, чтобы он правильно читал.
Я думал, что это должно быть стандартным использованием, кроме. Что делать тогда?
Ожидайте и тому подобное, все дело с ttys, а мир tty довольно беспорядочный. Нелегко написать правильный ожидающий скрипт для новых пользователей.
Самая распространенная ошибка может заключаться в том, что вы забыли вызвать «ожидание eof» в конце скрипта. :)
Попробуйте мой секспект. Его поведение по умолчанию более удобно для пользователя (например, в большинстве случаев можно забыть о eof).





Следует отметить одну вещь: когда heredoc заканчивается (в EOF), процесс ожидания завершается, и процесс sshfs будет убит.
Вам нужно продолжать ожидать запуска, и вы, вероятно, захотите запустить его в фоновом режиме:
function mount_sshfs_with_2fa() {
# Get the FTP password from the encrypted file
local password=$(gpg --decrypt encrypted_password.txt)
# Prompt for verification code
read -p "Verification code: " otp
{
expect << EOF
spawn sshfs user@host:/remote/ /local/
expect -re {Verification code: $}
send -- "$otp\r"
expect -re {Password: $}
send -- "$password\r"
set timeout -1
expect eof
EOF
} &
}
Я немного запутался здесь, я ожидаю, что sshfs продолжит работать в фоновом режиме даже после остановки ожидания!
И что, если это был просто ssh?
Что происходит, когда вы запускаете sshfs из командной строки? Вы вводите свой OTP и пароль, и что дальше?
Оно работает. После sshfs user@host:/remote/ /local/ (и предоставления otp и пароля) он монтируется и возвращается к $.
Кстати, вышеуказанное решение не работает. Я никогда не думал, что передать пароль может быть так сложно!
Скорее всего, его убил SIGHUP. Попробуйте так:
expect << EOF
spawn -ignore SIGHUP sshfs user@host:/remote/ /local/
set timeout -1
expect -re "code:"
send -- "$otp\r"
expect -re "Password:"
send -- "$password\r"
expect eof
sleep 1
EOF
Я не знаю как, но это работает! Большое спасибо!
технически говоря, sshfs (если он хорошо реализован) должен быть невосприимчив к SIGHUP (исходящему от tty) после того, как он запустится в фоновом режиме. но кто знает. :)
Я удивлен, что OTP запрашивается перед паролем. Тем не менее, мы ожидаем показать вам, что он делает:
expect -d << EOF