Gnu Screen: Выполнение команды при присоединении

Gnu Screen: Выполнение команды при присоединении

Есть ли способ, чтобы GNU Screen определял, когда он подключается, и выполнял скрипт оболочки, который у меня есть, когда он подключается? Причина этого в том, что я хочу сохранить мои переменные отображения правильными для пересылки X11, но мне нужно определить, когда экран повторно подключается к другому компьютеру, чтобы запустить мой скрипт.

Спасибо.

решение1

Вы можете запустить screen -S foo -X setenv DISPLAY "$DISPLAY"; screen -S foo -rd, чтобы изменить среду процесса screenперед присоединением. Это не повлияет на существующие окна.

Возможно, вы можете настроить свою оболочку на проверку обновленной DISPLAY(и любой другой соответствующей переменной, такой как XAUTHORITY) каждый раз, когда они показывают приглашение. (Это означает, что вам, возможно, придется нажать Enterодин раз, если оболочка находилась в приглашении, когда вы присоединили сеанс.) Bash оценивает $PROMPT_COMMANDперед отображением каждого приглашения. Zsh запускает precmdфункцию перед отображением каждого приглашения. Например, если вы поместили желаемые назначения окружения в скрипт ~/var/run/screen-12345.foo.env-update.sh(где 12345 — это pid процесса экрана, а foo— имя сеанса), вы можете использовать что-то вроде (для zsh, не проверено; я не думаю, что вы сможете обойтись без ответвления в bash):

precmd () {
  local now=$SECONDS
  set ~/var/run/"screen-$STY.env-update.sh"(Nms-$(($now-$screen_env_time)))
  if [[ $# -ne 0 ]]; then
    screen_env_time=$now
    . ~/var/run/"screen-$STY.env-update.sh"
  fi
}

Еще одна вещь, которую вы можете сделать из $PROMPT_COMMANDили precmd, в некоторых операционных системах, это прочитать окружение родительского процесса (это предполагает, что вы обновили окружение процесса screen). Например, в Linux с zsh (делайте это только если работаете под screen):

precmd () {
  local record
  while read -r -d $'\0' record /proc/$PPID/environ; do
    case ${record%%=*} in
      DISPLAY|XAUHORITY) export $record;;
    esac
  done
}

Технически, вы можете изменить среду другого процесса, используя отладчик. Но есть большая вероятность, что это приведет к сбою этого процесса, поскольку внутренние структуры данных программы не будут соответствовать данным, хранящимся в ядре.

Обратите внимание, что ни одно из этих решений не принесет пользы, если вы запустите ssh внутри окна Screen.

решение2

То, что вы в конечном итоге хотите, не может быть сделано. Даже если вам удастся заставить screen запустить скрипт при подключении, он все равно не сможет изменить среду дочерних процессов.

решение3

Я думаю, что решение Джайлса является наиболее общим, но у него есть два недостатка: (1) оно не работает, пока вы не запустите команду, после повторного присоединения, и (2) команда выполняется при каждом новом приглашении командной строки. (Что я могу сказать, я ненавижу тратить циклы ЦП). Есть альтернатива, но она тоже не идеальна: при screenповторном присоединении к терминалу другого размера, чем предыдущее окно, screenотправляет SIGWINCHсигнал оболочке, который вы можете перехватить:

trap some_function SIGWINCH

Я написал скрипт оболочки (будет предоставлен вместе с .bashrc), который использует этот факт для обработки перезаписи SSH_AUTH_SOCK и связанных переменных при повторном подключении отсоединенного терминала. Смотрите проект здесь:https://gitlab.com/otheus.uibk/bashrc-ssh-agent. Скрипт можно легко модифицировать для интеграции с PROMPT_COMMAND.

Может быть, мы можем обновиться screenс опцией принудительного SIGWINCH при повторном подключении? Я сейчас использую 4.1.0 (поставляется с RedHat 7), но текущая версия — 4.6.

Связанный контент