Как я могу решить эту проблему? У меня есть сценарий bash (под Ubuntu Server), выполняющий несколько соединений SSH, несколько раз выполняет некоторые удаленные передачи, например rsync.
Моя проблема в том, что я не хочу вводить пароль несколько раз. Но я не хочу использовать обмен открытым ключом SSH, потому что, если у кого-то есть ключ, он сможет подключить удаленный компьютер.
Я бы хотел следующее:
Нечто похожее, как работает sudo, только с ssh.
Есть идеи, как это решить?
РЕДАКТИРОВАТЬ1:
Я обнаружил новую функцию SSH под названием ssh multiplexing. Возможно, используя это, я смогу достичь желаемой цели.
https://unix.stackexchange.com/questions/50508/reusing-ssh-session-for-repeated-rsync-commands
Это сработает?
(Повторная публикация моего комментария как ответа на запрос от klor).
Это не то, что вы хотите услышать, но это то, для чего нужна аутентификация на основе ключей. Пока вы добавляете парольную фразу в свой закрытый ключ, это не менее безопасно, чем аутентификация по паролю.
Ты можешь использовать ssh-agent
чтобы не вводить пароль каждый раз, а -t
возможность ssh-agent
даст вам поведение тайм-аута, которое вам нужно.
# start a shell under ssh-agent with a 5-minute timeout for keys loaded with ssh-add
ssh-agent -t 300 /bin/bash
# add your key(s) to the agent; ssh-add will prompt for passphrase, if one is set
ssh-add
# do some stuff
ssh remote.server cat /some/file
rsync file1 file2 klor@remote.server:/some/directory
# after 300 seconds, timeout reached, run ssh-add again to re-add your keys
ssh-add
Вашему сценарию потребуется некоторая логика для определения времени ожидания. Один из способов - бежать ssh
и rsync
с участием -o BatchMode=yes
, что предотвратит интерактивные методы аутентификации, поэтому, если ключ больше не используется, ssh
выйдет вместо запроса пароля. Вы можете использовать код выхода, чтобы определить, нужно ли вам запускать ssh-add
очередной раз; $?
должен быть установлен на 255
в таком случае.
Вам все равно нужно будет решить, как передать кодовую фразу в ssh-add
, потому что он не дает возможности принять его программно. Если ваш скрипт не предложит вам ввести его вручную, вам, вероятно, потребуется использовать expect
для этой части, а это будет означать жесткое кодирование парольной фразы где-нибудь.
Кажется, я нашел идеальное решение для своих нужд:
Повторное использование сеанса ssh для повторяющихся команд rsync
#!/bin/bash
# Create ssh-mux (SSH multiplex) dir only if not exists
[[ ! -d dir ]] || mkdir ~/.ssh/ssh-mux
apache_site_path_source="/var/www/source_site"
apache_site_path_target="/var/www/target_site"
# Solution: Start SSH multiplexing session (works fine)
# https://unix.stackexchange.com/questions/50508/reusing-ssh-session-for-repeated-rsync-commands
sudo ssh -nNf -o ControlMaster=yes -o ControlPath="~/.ssh/ssh-mux/%L-%r@%h:%p" root@192.168.0.1
sudo rsync -av --progress -e 'ssh -l root -p 22 -o "ControlPath=~/.ssh/ssh-mux/%L-%r@%h:%p"' 192.168.0.1:${apache_site_path_source}/. ${apache_site_path_target}/;
printf "\n\n\n\n\n\n"
sudo rsync -av --progress -e 'ssh -l root -p 22 -o "ControlPath=~/.ssh/ssh-mux/%L-%r@%h:%p"' 192.168.0.1:${apache_site_path_source}/. ${apache_site_path_target}/;
printf "\n\n\n\n\n\n"
sudo rsync -av --progress -e 'ssh -l root -p 22 -o "ControlPath=~/.ssh/ssh-mux/%L-%r@%h:%p"' 192.168.0.1:${apache_site_path_source}/. ${apache_site_path_target}/;
printf "\n\n\n\n\n\n"
# Finish SSH multiplexing session
sudo ssh -O exit -o ControlPath="~/.ssh/ssh-mux/%L-%r@%h:%p" root@192.168.0.1
Это решение запрашивает пароль только один раз, а затем выполняет rsync 3 раза, не запрашивая пароль снова. Каждый rsync повторно использует соединение SSH с использованием мультиплексирования SSH.
Возможно, можно изменить конфигурацию SSH и сохранить настройки мультиплексирования SSH, но при использовании этого решения нет необходимости изменять конфигурацию сервера, скрипт работает как есть.
Реализация Джеймс Снирингеркомментарий как сценарий профиля.
# This script must be sourced to be useful. For example, if you name this script
# ~/.bash_autossh, at the end of .bashrc, source $HOME/.bash_autossh
# Tested in bash & zsh
# MIT license, if you need a license.
# An absolute path to a private key:
AUTOLOADSSHID=$HOME/.ssh/id_ecdsa
# Timeout is in seconds, optional:
SSHID_TIMEOUT=60
auto_init_ssh_agent() {
if [ "${SSH_AGENT_PID}x" = "x" ] || \
[ "${SSH_AUTH_SOCK}x" = "x" ] || \
ps -p "${SSH_AGENT_PID}" >& /dev/null || \
[ ! -e "${SSH_AUTH_SOCK}" ]; then
# There are problems with the agent, initialize a new agent.
# Agents started this way should be manually stopped with ssh-agent -k
source <(ssh-agent -s)
fi
if ! ssh-add -l | grep "${AUTOLOADSSHID}" >/dev/null; then
# The autoload key is not present, try to load it.
SSH_ADDTL_ARGS=()
if [ "${SSHID_TIMEOUT}x" != "x" ]; then
SSH_ADDTL_ARGS+=( -t "${SSHID_TIMEOUT}" )
fi
# This may ask for a password, as appropriate
ssh-add "${SSH_ADDTL_ARGS[@]}" "${AUTOLOADSSHID}"
unset SSH_ADDTL_ARGS
fi
}
_autossh() {
args=( "$@" )
auto_init_ssh_agent
ssh "${args[@]}"
}
alias autossh=_autossh
Затем вы можете запустить команду autossh myserver
и он автоматически инициализирует агент, если он недоступен. Псевдоним предназначен для предотвращения случайного вызова интерактивной функции из сценария.
Проблема в том, что в системах, которые не запускают агент автоматически с сеансом WM, это может засорить вашу машину процессами ssh-agent, вам может потребоваться ssh-agent -k
чтобы закончить это, или killall ssh-agent
. Некоторые дополнительные сценарии могут потребоваться, если вы хотите использовать один ssh-агент для всего сеанса входа в систему или для нескольких сеансов процессов.
Я обычно говорю тебе попробовать expect
, но в этом случае я думаю, что лучше использовать sshpass, его очень легко установить и использовать, здесь я публикую несколько примеров использования
sshpass -p<pass> ssh <args>
sshpass -pfoobar ssh -o StrictHostKeyChecking=no user@host command_to_run
радоваться, веселиться :)
ИЗМЕНИТЬ 1
по сценарию
#!/bin/bash
read -p "give me the password" pass
sshpass -p"$pass" ssh -o StrictHostKeyChecking=no user@host command_to_run