По итогам обсуждения у Витуса (1 серия, 2 серия) собрал и причесал:
source_ssh_auth:
Что делает. Если видит в переменной SSH_AUTH_SOCK сокет ssh-агента (но не симлинк на него — поэтому ! -L), делает на него симлинк с well-known именем. После чего переставляет переменную SSH_AUTH_SOCK.
Единственная переменная часть в имени — hostname. Защита от проблем, возникающих в случае с NFS-mounted home.
Что позволяет. Типичная ситуация: с хоста A, где агент, идем с форвардом агента на хост B, запускаем там screen или tmux, и оттуда ходим на хосты C, D и т.д. Если не выполнить fix_ssh_auth_sock, то после первого detach, по любой причине, $SSH_AUTH_SOCK внутри screen останется негодным навсегда. А он случайный. А если выполнить, то после перелогина и подсоединения к сессии он снова станет годным. Будет через симлинк указывать на новый сокет.
Запускается... Во-первых, не запускается, а читается. "." (source), в смысле. Потому что надо переставить переменную. У меня из .zprofile, а остальным рекомендуется .profile или .bash_profile. Синтаксис намеренно выдержан таким, чтобы можно было запускать даже из dash.
Не надо запускать это из НЕинтерактивного шелла — агент отвалится после завершения команды. Честно говоря, маны на bash и dash мутны в части того, выполняется ли .profile из логинного, но неинтерактивного шелла. Подозреваю, что нет, но экспериментируйте себе сами.
.zlogin:
Что делает. При интерактивном логине по ssh молча запускает screen в режиме «если есть запущенная сессия, подцепиться к ней (к самой свежей по времени создания, если их несколько), НЕ отцепляя других возможных клиентов той же сессии; если ее нет, создать и подцепиться». Согласно man screen, именно с этими ключами screen запускается, если указать его в качестве логинного шелла.
Что позволяет. Не попадать в ситуации, когда надо бы отцепиться от сервера (положить спать ноутбук, с которого зашли), а команда на сервере оказалась слишком долгоиграющей, и прерывать ее не хочется. Или в ситуации, когда и не стал бы отключаться, да канал упал, не спросив. Общий принцип: зашел на удаленную машину — запусти screen.
Запускать. У меня из вышеуказанного .zlogin. У кого .profile или .bash_profile, оттуда последней командой.
source_ssh_auth:
fix_ssh_auth_sock () {
if [ -e "$HOME/bin/fixssh" ]; then /bin/rm -f "$HOME/bin/fixssh"; fi
if [ -S "$SSH_AUTH_SOCK" -a ! -L "$SSH_AUTH_SOCK" ]; then
local new_ssh_auth_sock_dir
new_ssh_auth_sock_dir="$HOME/.ssh/auth_sock"
local new_ssh_auth_sock
new_ssh_auth_sock="$new_ssh_auth_sock_dir/auth_sock.$(hostname)"
if [ ! -d "$new_ssh_auth_sock_dir" ]; then
mkdir -p "$new_ssh_auth_sock_dir" || return
fi
ln -sf "$SSH_AUTH_SOCK" "$new_ssh_auth_sock" || return
SSH_AUTH_SOCK="$new_ssh_auth_sock"
export SSH_AUTH_SOCK
fi
}
case "$DISPLAY" in
# don't run fix_ssh_auth_sock if logged in locally in X
# because otherwise you'll lose connection to local ssh agent
# after first remote or terminal login to this host
:*) ;;
*) fix_ssh_auth_sock ;;
esac
Что делает. Если видит в переменной SSH_AUTH_SOCK сокет ssh-агента (но не симлинк на него — поэтому ! -L), делает на него симлинк с well-known именем. После чего переставляет переменную SSH_AUTH_SOCK.
Единственная переменная часть в имени — hostname. Защита от проблем, возникающих в случае с NFS-mounted home.
Что позволяет. Типичная ситуация: с хоста A, где агент, идем с форвардом агента на хост B, запускаем там screen или tmux, и оттуда ходим на хосты C, D и т.д. Если не выполнить fix_ssh_auth_sock, то после первого detach, по любой причине, $SSH_AUTH_SOCK внутри screen останется негодным навсегда. А он случайный. А если выполнить, то после перелогина и подсоединения к сессии он снова станет годным. Будет через симлинк указывать на новый сокет.
Запускается... Во-первых, не запускается, а читается. "." (source), в смысле. Потому что надо переставить переменную. У меня из .zprofile, а остальным рекомендуется .profile или .bash_profile. Синтаксис намеренно выдержан таким, чтобы можно было запускать даже из dash.
Не надо запускать это из НЕинтерактивного шелла — агент отвалится после завершения команды. Честно говоря, маны на bash и dash мутны в части того, выполняется ли .profile из логинного, но неинтерактивного шелла. Подозреваю, что нет, но экспериментируйте себе сами.
.zlogin:
if [ -n "$SSH_CONNECTION" ]; then exec screen -xRR; fi
Что делает. При интерактивном логине по ssh молча запускает screen в режиме «если есть запущенная сессия, подцепиться к ней (к самой свежей по времени создания, если их несколько), НЕ отцепляя других возможных клиентов той же сессии; если ее нет, создать и подцепиться». Согласно man screen, именно с этими ключами screen запускается, если указать его в качестве логинного шелла.
Что позволяет. Не попадать в ситуации, когда надо бы отцепиться от сервера (положить спать ноутбук, с которого зашли), а команда на сервере оказалась слишком долгоиграющей, и прерывать ее не хочется. Или в ситуации, когда и не стал бы отключаться, да канал упал, не спросив. Общий принцип: зашел на удаленную машину — запусти screen.
Запускать. У меня из вышеуказанного .zlogin. У кого .profile или .bash_profile, оттуда последней командой.
no subject
Мне почему-то это редко нужно. Хотя на удалённые сервера с отваливающимися соединениями я хожу постоянно.
Но раз есть готовое решение — возьму, пожалуй, на вооружение.
Меня смущает
exec— если у меня проблемы с запускомscreen, я потом смогу зайти интерактивно и починить? Не отключитexecмне возможность залогиниться?no subject
security implications вроде бы тоже не просматривается
no subject
no subject
no subject
no subject
да, немножко ядерное оружие, но
no subject
А без exec у тебя оказывается достаточно большая вероятность что на экране будут валяться окна удаленных сессий без screen.
no subject
[ -n "$SSH_CONNECTION" ] && screen -xRR
;-P
no subject
no subject
или я в чего-то не увидел?
no subject
Но после того как попробовал завершить удаленную сессию, понял что это неправильно, и надо делать как предлагает Артем.
no subject
я натурально не вижу семантической разницы (ну, sirca exec)
no subject
Потому что обычно я как раз хочу, чтобы он обращал моё внимание на факт неудачного завершения запущенной мной программы.
no subject
Это не считается интерактивным логином.
no subject
ssh -t $host bash --norcno subject
Есть /tmp/user/$(id -u), есть /run/screen/S-${LOGNAME}
Эти места оказываются заведомо локальны для машины и не то чтобы совсем заведомо, но в типичной ситуации writable для юзера.
no subject
no subject
no subject
no subject
no subject
no subject
no subject
no subject
Зато вот идея, что $HOME/.ssh тоже может не быть writable, у меня встречается. Правда, у служебных юзеров, под которыми могут заходить разные люди и к которым поэтому вообще не стоит форвардить агента.
(Кстати, только что дошло: мы привыкли прописывать ForwardAgent yes для хоста, не глядя на юзера на том конце. Для серверов, где есть такие служебные юзеры, и ты доверяешь не всем, кто туда ходит, это чревато боком, и надо ещё Match с user прописывать. Ну, если там есть недоверенный рут, то туда вообще нельзя агента форвардить.)
no subject
no subject
чтобы от луркеров защититься
и в хомяк его имя линком (поэтому в оригинале хост)
no subject
no subject
zshнет$HOSTNAME— вместо$(hostname)?no subject
Впрочем, мы тут с Витусом обсуждаем что-то в духе создавать линк не в ~/.ssh/auth_sock/ и добавлять $(hostname) к имени сокета, а в /tmp/user-$(id -u)/ и ничего к имени не добавлять.
/tmp крайне редко бывает NFS-shared, даже если она NFS-mounted. Но с другой стороны, писать туда может кто попало, поэтому обеспечить безопасность такого решения я бы не взялся.
export SSH_AUTH_SOCK
exportлишний.SSH_AUTH_SOCKк этому моменту уже проэкспортирован, а второй раз незачем.Хуже от этого не будет, конечно.
Или в
zshдругие правила переэкспортирования переменных?if [ -n "$SSH_CONNECTION" ]; then exec screen -xRR; fi
exec screen -xRRу меня падает. Запускается и сразу на выход. Я подумал и стал подозревать, что проблема в том, что внутриscreenтоже запускается.profile, в котором запускаетсяexec screen;screenэто отлавливает и прекращает цикл.Поставил защиту:
[ -n "$SSH_CONNECTION" -a -z "$STY" ] && exec screen -xRR. Теперьscreenзапускается, но перестал работатьrsync. Похоже, у меня неинтерактивныйsshвсё равно запускает.profile. Поставил ещё одну защиту, от неинтерактивного использования:-t 0. Пока всё работает. В целом конец моего.profileтеперь выглядит так:Re: if [ -n "$SSH_CONNECTION" ]; then exec screen -xRR; fi
-t 0не достаточно — эта защита не срабатывает в ситуацииssh -t host command. Пришлось усилить защиту — добавил проверку флагаi(интерактив) в переменной$-:# If not running interactively, don't do anything case $- in *i*) ;; *) return ;; esac # Stop if non-interactive shell [ -z "$PS1" ] && return if [ -n "$SSH_CONNECTION" -a -z "$STY" -a -t 0 ] && which screen >/dev/null 2>&1 then exec screen -xRR -S default fiRe: if [ -n "$SSH_CONNECTION" ]; then exec screen -xRR; fi
Бардак с файлами инициализации в bash для меня тоже один из поводов пользоваться zsh.
Re: if [ -n "$SSH_CONNECTION" ]; then exec screen -xRR; fi
.bashrc, а теперь вот скопировал в.profile:-)