Когда я запускаю оболочку, в моем случае bash и/или zsh, какие строки мне нужно добавить в .zshrc и/или .bashrc, чтобы проверить, запущена ли уже программа, и если программа еще не запущена, запустить ее?
Пример: Я запускаю новую оболочку zsh. Если top еще не запущен, я бы хотел запустить top и передать ему управление оболочкой. Если top уже запущен в другом окне, я бы хотел, чтобы .zshrc продолжил загрузку и предоставил мне открытый терминал.
6-16 Обновление:
if ! pgrep -U $USER top >/dev/null; then
exec top
fi
Скрипт выше удовлетворяет мой запрос. Флаг -q не сработал бы для меня, потому что -q не является опцией в моей системе. Поэтому мне пришлось перенаправить PID в /dev/null. Спасибо mveroone, Kusalananda и Thomas Dickey.
У меня есть некоторые особенности, которые выходят за рамки исходного вопроса. Предположим, что я работаю в однопользовательской системе, где я могу стать root без необходимости вводить пароль. Как бы я мог автоматически запустить top как root, если бы мне это было нужно?
6-18 Хорошо, проблема с функцией ползучести при передаче команды от имени root решена. Я использую это для запуска нескольких
Спасибо за все содержательные ответы.
решение1
Используйте pgrep
так:
if ! pgrep -u $USER top >/dev/null 2>&1; then
exec top
fi
Объяснение:
- Утилита
pgrep
завершается с нулевым кодом выхода, если команда может быть найдена работающей. Поэтому отмените тест. - Также ограничьте его текущим пользователем с помощью
-u $USER
, чтобы он по какой-то причине не подхватил чужие процессы.$USER
— это стандартная переменная оболочки. Если это по какой-то причине не определено, попробуйте использовать$LOGNAME
вместо этого , а если это не сработает, используйте$( id -n -u )
(но в этот момент вы должны спросить себя, что происходит, потому что$LOGNAME
этотакжестандартная переменная оболочки). - Нам не нужен вывод из
pgrep
, поэтому перенаправим стандартный вывод и потоки ошибок в/dev/null
.
Если top
(или что-то еще) не будет обнаружено, exec
необходимо заменить оболочку, как и спросил автор вопроса.
Это должно работать во всех sh
совместимых оболочках.
EDIT: pgrep
Реализация в системах BSD (OS X, OpenBSD, ...) имеет -q
опцию, которая заставляет ее отбрасывать любой вывод, но в pgrep
Linux, по-видимому, нет этого флага. В системах BSD используйте это вместо немного уродливого перенаправления на /dev/null
.
решение2
Если программа всегда запускается из оболочки и у вас есть полный контроль над ней (т. е. она не закодирована жестко внутри сторонней программы), то вы можете использовать какой-либо механизм блокировки, например lockfile
или flock
. Например, добавив
flock -n /tmp/top -c top
в .bashrc
/, .zshrc
вы гарантируете, что только первый экземпляр оболочки выполнит команду top
(если только вы не убьете его, а затем запустится другой).
Возможно, вы захотите создать функцию, чтобы иметь возможность запускать команду вручную (а не только при инициализации оболочки):
mytop () { flock -n /tmp/$0 -c top; }
И просто бегайте mytop
, когда захотите.
решение3
Согласившись, что pgrep
это правильный путь, есть некоторые подводные камни. Вам не нужно использовать эту -q
опцию, поскольку вы можете перенаправить вывод, pgrep
чтобы устранить это:
pgrep -U $USER top >/dev/null || exec top
Подводные камни кроются в том, что это не стандартная утилита, поэтому вам следует помнить, что она может быть непереносимой. Вот несколько ссылок на man-страницы, которые помогут:
Переменная окружения USER
более устоялась, но, по-видимому, не входит в список POSIX для оболочки (см.2.5.3 Переменные оболочки). Скорее, он отмечает, что USER
это одна из многих переменных, которые, как известно, используются (см. примечание в8.1 Определение переменной среды).
Это работает top
каксам, конечно. Если вы решили запустить его каккорень, то вы можете изменить $USER
на root
и затем запустить top
с помощью sudo
(предпочтительно) или su
. Ни один из них не входит в POSIX (см. список). Последний ( su
) доступен везде в Unix-подобных системах, но sudo
обычно является предпочтительным. Так что вам придется
pgrep -U root top >/dev/null || exec sudo top
Если вы не настроили sudo
защиту от ввода пароля, при запуске оболочки вам будет предложено ввести пароль top
.
решение4
Я бы добавил такой фрагмент в свой .zshrc (или другой):
если pgrep -u $USER имя_программы затем exec имя_программы фи
Предостережение :Я не тестировал этот код. Пожалуйста, не используйте его на root или на единственном пользователе, который у вас есть на сервере. Убедитесь, что вы можете восстановиться в случае сбоя.