Как узнать, работает ли я вложенная оболочка?
При использовании оболочки * nix (обычно bash) я часто создаю суб-оболочку, с которой я могу позаботиться о небольшой задаче (обычно в другом каталоге), а затем выйти из нее, чтобы возобновить сеанс родительская оболочка.
Время от времени я потеряю информацию о том, запускаю ли я вложенную оболочку или в оболочку верхнего уровня, и я случайно создаю дополнительную суб-оболочку или выйду из верхнего уровня по ошибке.
Есть ли простой способ определить, запущен ли я во вложенной оболочке? Или я перехожу к своей проблеме (путем нереста суб-оболочек) совершенно неправильно?
Ответы
Ответ 1
Переменная $SHLVL
отслеживает уровень вложенности оболочки:
$ echo $SHLVL
1
$ bash
$ echo $SHLVL
2
$ exit
$ echo $SHLVL
1
В качестве альтернативы нерестам суб-оболочек вы можете нажимать и вызывать каталоги из стека и оставаться в одной оболочке:
[[email protected] /old/dir]# pushd /new/dir
/new/dir /old/dir
[[email protected] /new/dir]# popd
/old/dir
[[email protected] /old/dir]#
Ответ 2
Вот упрощенная версия части моего приглашения:
PS1='$(((SHLVL>1))&&echo $SHLVL)\$ '
Если я не во вложенной оболочке, это не добавляет ничего лишнего, но показывает глубину, если я нахожусь на любом уровне вложенности.
Ответ 3
Посмотрите $0
: если он начинается с минуса -
, вы находитесь в оболочке входа.
Ответ 4
pstree -s $$
весьма полезно видеть вашу глубину.
Ответ 5
Переменная среды $SHLVL
содержит "глубину" оболочки.
echo $SHLVL
Глубина оболочки также может быть определена с помощью pstree
(версия 23 и выше):
pstree -s $$ | grep sh- -o | wc -l
Я нашел второй способ быть более надежным, чем первый, значение которого было reset при использовании sudo
или стало ненадежным с env -i
.
Ни один из них не может корректно иметь дело с su
.
Информация может быть доступна в вашем приглашении:
PS1='\[email protected]\h/${SHLVL} \w \$ '
PS1='\[email protected]\h/$(pstree -s $$ | grep sh- -o | tail +2 | wc -l) \w \$ '
| tail +2
следует удалить одну строку из вывода grep
. Поскольку мы используем конвейер внутри подстановки "$(...)
", оболочке нужно вызвать под-оболочку, поэтому pstree сообщает об этом, а grep обнаруживает еще один уровень sh-
.
В дистрибутивах на основе debian pstree
является частью пакета psmisc
. Возможно, он не будет установлен по умолчанию для дистрибутивов без рабочего стола.
Ответ 6
ptree $$
также покажет вам, сколько уровней вы
Ответ 7
Я получаю root login.... bash...
поэтому для меня нужен 4-й элемент bash, нет grep и т.д.
pstree -p $$ | awk '{if ($ 4 ~ "bash" ) {print $0}}' | wc -l
работает лучше.
Мне нужно -p получить pid, а не pstree на основе строк.
Mac OSx 10.11.6
Я мог бы просто распечатать 4 доллара, но полезно видеть целые строки в отладках
Ответ 8
As @Джон Кугельман говорит, echo $SHLVL
расскажет вам глубину оболочки bash.
И, как показывает @Dennis Williamson, вы можете отредактировать ваше приглашение через переменную PS1
, чтобы оно напечатало это значение.
Я предпочитаю, чтобы он всегда печатал значение глубины оболочки, поэтому вот что я сделал: отредактируйте файл "~/.bashrc":
gedit ~/.bashrc
и добавьте следующую строку в конец:
export PS1='\$SHLVL'":$SHLVL\n$PS1"
Теперь вы всегда будете видеть распечатку вашего текущего уровня bash чуть выше вашего приглашения. Пример: здесь вы можете видеть, что я нахожусь на уровне bash (глубина) 2, как указано $SHLVL:2
:
$SHLVL:2
7510-gabriels ~ $
Теперь следите за подсказкой, когда я спускаюсь на некоторые уровни bash с помощью команды bash
, а затем возвращаюсь через exit
. Здесь вы видите мои команды и подсказку (ответ), начиная с уровня 2 и опускаясь до 5, затем возвращаясь к уровню 2:
$SHLVL:2
7510-gabriels ~ $ bash
$SHLVL:3
7510-gabriels ~ $ bash
$SHLVL:4
7510-gabriels ~ $ bash
$SHLVL:5
7510-gabriels ~ $ exit
exit
$SHLVL:4
7510-gabriels ~ $ exit
exit
$SHLVL:3
7510-gabriels ~ $ exit
exit
$SHLVL:2
7510-gabriels ~ $
Бонус: всегда показывайте в своем терминале ваш текущий git branch
, в котором вы тоже находитесь!
В вашем приглашении также отобразится ваша ветка git, над которой вы работаете, вместо этого используйте в файле "~/.bashrc" следующее:
git_show_branch() {
__gsb_BRANCH=$(git symbolic-ref -q --short HEAD 2>/dev/null)
if [ -n "$__gsb_BRANCH" ]; then
echo "$__gsb_BRANCH"
fi
}
export PS1="\e[7m\$(git_show_branch)\e[m\n\h \w $ "
export PS1='\$SHLVL'":$SHLVL $PS1"
Источник: я понятия не имею, откуда взялся git_show_branch()
, но я получил его от Джейсона Макмаллана 5 апреля 2018 года. Затем я добавил часть $SHLVL
, показанную выше, только на прошлой неделе.
Пример вывода:
$SHLVL:2 master
7510-gabriels ~/GS/dev/temp $
И вот скриншот, показывающий его во всей красе. Обратите внимание на название ветки git, master
, выделенное белым!
![enter image description here]()
Перекрестная ссылка:
Ответ 9
Если вы используете внутри подкоманды следующий код, вы получите 2:
ps | fgrep bash | wc -l
В противном случае это даст 1.
EDIT Хорошо, это не столь надежный подход, как было указано в комментариях:)
Другое дело:
ps -ef | awk '{print $2, " ", $8;}' | fgrep $PPID
даст 'bash', если вы находитесь в суб-оболочке.