Я подошел к этому, замаскировав команду exit
функцией; функция проверяет, находитесь ли вы в пределах экрана, и являетесь ли вы единственным дочерним процессом, оставшимся от этого экранного процесса.
exit() {
if [[ "$(ps -o pid= --ppid "$(ps -o ppid= -p "$$")" | wc -l)" -eq 1 ]]
then
read -p "Warning: you are in the last screen window; do you really want to exit? (y/n) "
case $REPLY in
(y*) command exit "$@" ;;
esac
else
# not within screen at all, or not within the last screen window
command exit "$@"
fi
}
Вам нужно будет включить эту функцию в свой профиль (bash ), например. ~/.bash_profile
. При запуске экрана он (, если не указано иное ), запустит экземпляр вашей $SHELL. Эта оболочка будет потомком экранного процесса. При выходе из дочерней оболочки приведенный выше код проверяет, сколько процессов являются дочерними по отношению к родительскому процессу текущей оболочки. Изнутри наружу:
$(ps -o ppid= -p "$$")
--запрашивает родительский PID (добавление =
подавляет строку заголовка )текущего процесса($$
)$(ps -o pid= --ppid... | wc -l)
--снова запрашивает список PID (без заголовка ), чей родительский PID является нашим родителем, затем подсчитывает количество строк вывода Если кажется, что мы являемся последним дочерним процессом сеанса экрана, он запрашивает подтверждение; если ответ начинается с буквы y
, функция вызывает «настоящую» команду exit
для выхода из оболочки; в противном случае функция завершается без выхода из оболочки.
Если мы не последний дочерний процесс, функция продолжается и завершается нормально.
Пара заметок по мере разработки:
Первоначально у меня было больше тестов в строке if
, чтобы увидеть, находимся ли мы в сеансе экрана, в том числе проверить, заполнено ли STY
и SHLVL
больше 1. screen устанавливает STY, и bash будет увеличивать SHLVL, но ни одна из этих переменных не предназначена только для чтения -, поэтому проверка недостаточно надежна, чтобы быть полезной.
также устанавливает переменную WINDOW
, но проверка ее на 0
ненадежна; вы можете открыть два окна, а затем закрыть окно 0
, оставив окно 1
последним.
Ввод EOF (обычно Control + D)будет, по умолчанию,заставить оболочку немедленно выйти, минуя эту функцию-оболочку. Лучшим обходным решением, которое я знаю, было бы установить для переменной IGNOREEOF
какое-то ненулевое значение -; это только отсрочит неизбежный выход оболочки.
Поскольку я использовал так много специфических функций bash-(и GNU procutils -)выше, я хотел также предоставить решение, совместимое с POSIX -. Строка ps
изменяется на схему ps... | grep -c
, чтобы зафиксировать количество процессов с определенным родительским PID. Другое изменение состоит в том, чтобы переработать -read -p
в отдельную подсказку и read
.
exit() {
parent="$(ps -o ppid= -p $$)"
if [ "$( ps -eo ppid= | grep -c "^ *${parent}\$" )" -eq 1 ]
then
printf "Warning: you are in the last screen window; do you really want to exit? (y/n) "
read REPLY
case $REPLY in
(y*) command exit "$@" ;;
esac
else
# not within screen at all, or not within the last screen window
command exit "$@"
fi
}
gpg --gen-key --homedir /home/NEWUSER/.gnupg --passphrase "PASSWORD" --pinentry-mode loopback
Я столкнулся с чем-то очень похожим на это...
В моем случае это произошло из-за того, что у меня был запущен gpg-agent
и я удалил файлы, на которые он ссылался, чтобы «начать заново». Убив старый gpg-agent
я решил проблему.