Обнаружение, если инструмент уже выполняется, но ТОЛЬКО для текущего пользователя

До сих пор я использовал

pidof -o %PPID -x "my-tool"

Чтобы обнаружить pid исполняемого экземпляра моего инструмента.

Это короткая версия файла my-tool, исполняемый скрипт bash

#!/bin/bash 

if pidof -o %PPID -x "my-tool"; then
   echo "Already running"
   exit 1
fi

 ... if not running go on 

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

Обратите внимание, что мне нужен тест, чтобы создать что-то вроде синглтона. Если инструмент будет запущен, и будет запущен другой экземпляр, он закроется.

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

Как?

1
задан 26 July 2016 в 15:33

3 ответа

Вы можете использовать pgrep fo find, если процесс выполняется конкретным пользователем, а затем запустить процесс, если он уже не запущен пользователем:

#!/bin/bash
if pgrep -u "$USER" my-tool &>/dev/null; then
    echo 'You already have my-tool running'
else
    /path/to/my_tool
fi

Переменная среды, $USER, будет расширен до текущего пользователя, то есть пользователя, выполняющего сценарий. Поскольку нас интересует только то, работает ли my-tool или нет, поэтому достаточно использовать статус выхода непосредственно с конструкцией if.

Использовать этот скрипт как оболочку для запуска my-tool и заставьте пользователей использовать это только или переименуйте его как my-tool и переименуйте исходный my-tool в другое (и измените имя внутри скрипта тоже).

7
ответ дан 23 May 2018 в 07:46
  • 1
    Я не могу сделать обертку, долгую историю, ... как я могу исключить текущий PID процесса? – realtebo 26 July 2016 в 15:26
  • 2
    @realtebo ummm..exclude Значение PID? – heemayl 26 July 2016 в 15:53

Попробуйте это с помощью этого фрагмента:

#!/bin/bash
MyProcessName=$(ps -p $$ -o args=)
Mypid=$$
AllPids=$(pgrep -fu "$(whoami)" "$MyProcessName")
AllPids=$(tr "\n" ' ' <<<"$AllPids")
Pids=$(sed "s/$Mypid//" <<<"$AllPids")
echo "$$: Instances including itself: $AllPids"
echo "$$: Instances different from itself: $Pids"

Важно не писать pgrep|tr, потому что это будет fork в одну и ту же именованную оболочку.

2
ответ дан 23 May 2018 в 07:46

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

lockfile = "~/lockfile"
(
 if flock -n 200; then
    command
 else
    echo "Could not get lock $lock_file
 fi
) 200>$lock_file

«команда» может быть любой командой bash или скриптом.

man flock дает примеры использования

2
ответ дан 23 May 2018 в 07:46
  • 1
    Действительно, я вообще не знал команду flock – realtebo 9 August 2016 в 15:19

Другие вопросы по тегам:

Похожие вопросы: