Как предотвратить повторный запуск сценария bash при открытии терминала

Вопрос или проблема

Как предотвратить повторный запуск сценария bash при открытии терминала

Я физически подключен к машине и использую Arch Linux. Я использую арабский язык в терминале и использую BiCon для добавления поддержки двунаправленного текста в терминале (я использую st). Я хочу, чтобы программа запускалась автоматически при открытии терминала и очищала сообщение, которое она выводит при старте, поэтому я сделал скрипт:

$ cat biconscript
bicon 
clear

и положил его в .bashrc, и вот вывод: строка bicon выполняется повторно.

скриншот проблемы

Что я могу добавить в скрипт bash, чтобы он остановился после первого выполнения?

$ cat .bashrc

# Если выполняется не интерактивно, ничего не делать
[[ $- != *i* ]] && return

#alias ls="ls --color=auto"
alias ls="lsd"
alias grep='grep --color=auto'
alias p='sudo pacman'
alias ..='cd ..'
alias ...='cd ../../'
alias ....='cd ../../../'
alias ll="lsd -l -F"
alias la="lsd -aF "
alias sdn='sudo shutdown now'
alias q='exit'
alias update="p -Syu"
alias changeb='feh --bg-scale --randomize ~/Downloads/wall/'
export EDITOR=nvim #устанавливаем nvim как редактор по умолчанию
export MANPAGER="nvim +Man!"
PS1='\[\e[38;5;232;107m\]>\[\e[48;5;252m\]>\[\e[48;5;251m\]>\[\e[0m\] \[\e[38;5;26;1m\]@\[\e[0m\] \[\e[1m\]\w\[\e[38;5;46m\]$\[\e[0m\] '
set -o vi       #установка режима vim
shopt -s autocd #не нужно вводить cd для смены каталога
PROMPT_DIRTRIM=2
eval "$(zoxide init bash)" #добавляет команду "z", связанную с приложением zoxide, она работает как команда "cd", но умнее
function yy() {            # позволяет yazi существовать с изменением текущего каталога
  local tmp="$(mktemp -t "yazi-cwd.XXXXXX")"
  yazi "$@" --cwd-file="$tmp"
  if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then
    builtin cd -- "$cwd"
  fi
  rm -f -- "$tmp"
}
biconscript #скрипт для добавления арабского

Похоже, что bicon всегда запускает новую сессию оболочки, и поэтому снова считывает ваш ~/.bashrc, который затем снова вызывает bicon, что снова считывает ваш ~/.bashrc, что снова вызывает bicon и так далее бесконечно. Это подразумевается в странице man инструмента, которая гласит:

SHELL Если переменная SHELL существует, оболочка, созданная bicon, будет именно этой оболочкой. Если SHELL не установлена, предполагается оболочка Bourne. (Большинство оболочек устанавливают эту переменную автоматически).

Так что bicon создает новую оболочку, вот почему вы это видите. Так что, боюсь, вы не можете добавить этот инструмент в ваш ~/.bashrc так просто. Однако вы можете обернуть это в простой if, который сначала проверяет, запущен ли экземпляр bicon, и запускает его только в том случае, если такового нет:

if ! pkill -0 bicon; then
  bicon
fi
clear

Важно, чтобы clear было вне if, потому что это должно выполняться созданной оболочкой, так что только если bicon запущен. Теперь это работает, но это означает, что у вас будет работать bicon только в первом открытом терминале и до его закрытия. Так что если вы откроете новый терминал, пока старый все еще работает, вы не получите bicon в новом.

Чтобы обойти это, если вы используете bash, вы можете воспользоваться переменной SHLVL. См. man bash:

SHLVL Увеличивается на единицу каждый раз, когда создается экземпляр bash.

Эта переменная считает количество экземпляров bash, которые вы запустили в текущей сессии. На графических системах она, вероятно, будет равняться 2, когда вы открываете терминал, предположительно потому что ваша среда рабочего стола уже запущена в одном экземпляре bash:

скриншот терминала, показывающий что SHLVL равен 2

Если вы откроете новую оболочку как другой пользователь, то она будет равна 1:

terdon@oregano ~ $ sudo -iu bib
[bib@oregano ~]$ echo $SHLVL 
1
[bib@oregano ~]$ 

Итак, предполагая, что ваша система похожа на мою и у вас 2 для новых терминалов, вы можете добавить это в ваш ~/.bashrc:

if [ $SHLVL -le 2 ]; then
     bicon
fi
clear

Это запустит bicon только один раз для каждого открытого терминала.

Проверьте на своей системе, проверьте, равен ли в новом терминале ваш SHLVL 1 или 2, и адаптируйте соответственно (возможно, вы захотите использовать -le 1 вместо -le 2, если ваше значение равно 1).

Проблема заключается в рекурсивном запуске новых оболочек.

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

Если это не сработает, читайте дальше…

Дело в том, чтобы делать вещи, которые по своей природе рекурсивны, а затем добавлять дополнительный код для предотвращения рекурсии, создает хрупкий дизайн. Вы можете оказаться заблокированным, сделав незначительное изменение в вашем .bash_profile.

Подумайте о замене вашей оболочки для входа с bash на что-то, что устанавливает SHELL=/bin/bash, а затем запускает bicon; это станет программой, которая запускается в каждом новом терминале.

Вероятно, это будет скрипт в вашем каталоге ~/.local/bin или ~/bin, и вам придется указать его полный путь:

b=$( command -v bicon )
s=$HOME/.bin/bicon-login
mkdir -p "${s%/*}"
printf > "$s" '%s\n' \
  '#!/bin/bash' \
  "SHELL=/bin/bash exec -l $b"
chmod a=rx "$s"
sudo usermod -s "$s" "$USER"

Обратите внимание, что строка #!/bin/bash независима от вашей оболочки для входа; я выбрал bash, потому что он поддерживает exec -l, который говорит bicon, что это на самом деле ваша оболочка для входа.

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

Ответ или решение

Чтобы предотвратить повторный запуск вашего скрипта в начале терминала при использовании Bash, результатом чего является бесконечный цикл, необходимо рассмотреть несколько аспектов. Проблема возникает из-за того, что bicon запускает новый экземпляр оболочки, которая затем снова считывает ваш файл .bashrc и вновь запускает bicon. Вот несколько решений для этой проблемы.

Решение 1: Использование переменной SHLVL

Один из простых способов избежать бесконечного цикла — использование переменной окружения SHLVL, которая отслеживает уровень вложенности оболочек. В своем файле .bashrc, вы можете добавить условие, проверяющее значение этой переменной. Например:

if [ "$SHLVL" -le 2 ]; then
    bicon
fi
clear

Этот код запускает bicon только в первых двух уровнях оболочки. Проверьте значение SHLVL в новом терминале, выполнив команду echo $SHLVL, чтобы удостовериться, что ваше значение соответствует настройки, и при необходимости измените условие.

Решение 2: Проверка запущенных процессов

Также возможно использовать команду pkill для проверки, запущен ли уже процесс bicon, и запускать его только в случае, если он неактивен:

if ! pgrep -x "bicon" > /dev/null; then
    bicon
fi
clear

С помощью pgrep мы проверяем, работают ли экземпляры bicon, и запускаем его только в том случае, если ни одного экземпляра не найдено. Это предотвращает повторный запуск bicon, если он уже активен.

Решение 3: Изменение оболочки по умолчанию

Если вышеописанные методы вам не подходят, вы можете рассмотреть возможность изменения вашей входной оболочки на пользовательский скрипт, который запускает bicon при входе. Создайте скрипт, который будет использовать bicon следующим образом:

#!/bin/bash
SHELL=/bin/bash exec -l bicon

Сохраните его в директории ~/.local/bin/bicon-login, сделайте его исполняемым и измените оболочку вашего пользователя с помощью команды:

sudo usermod -s ~/.local/bin/bicon-login $USER

Дополнительные рекомендации

  1. Тестируйте скрипт на локальной машине, чтобы убедиться, что он работает, как ожидается.
  2. Обратите внимание на конфигурацию вашего терминала: Некоторые терминалы могут быть настроены для использования конкретной оболочки. Вы можете изменить это в настройках терминала, чтобы использовать вашу входную оболочку.
  3. Чистка файла .bashrc: Избегайте добавления множества сложных условий, которые могут привести к ошибкам.

Эти решения помогут вам избежать проблем с повторным запуском bicon в вашей терминальной среде на Arch Linux.

Оцените материал
Добавить комментарий

Капча загружается...