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

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

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

Обнаружить pid в конечном счете рабочего экземпляра моего-инструмента.

Это - короткая версия файла моего-инструмента, исполняемого сценария удара

#!/bin/bash 

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

 ... if not running go on 

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

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

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

Как к?

8
задан 26 July 2016 в 05:33

4 ответа

Использовать pgrep вместо этого:

pgrep -cxu $USER -f my-tool

Используемые опции:

   -c, --count
          Suppress  normal  output; instead print a count of matching pro‐
          cesses.  When count does not match anything, e.g. returns  zero,
          the command will return non-zero value.
   -x, --exact
          Only match processes whose names (or command line if -f is spec‐
          ified) exactly match the pattern.
   -u, --euid euid,...
          Only match processes whose effective user ID is listed.   Either
          the numerical or symbolical value may be used.

Если Вы хотите использовать это в сценарии удара, который проверяет, работает ли он уже, Вы могли бы использовать $0. Это расширяется до пути текущего сценария (например. /home/username/bin/foo.sh) но нам только нужно foo.sh. Для получения этого мы можем удалить все до последнего / использование инструментов обработки строк удара: ${0##*/}. Это означает, что мы можем сделать что-то как:

## If there are more than 1 instances of the current script run
## by this user
if [[ $(pgrep -cxu "$USER" "${0##*/}") -gt 1 ]];
then
        echo "Script already running, exiting."
        exit
fi

Вы могли бы также хотеть рассмотреть использование lockfiles для этого:

## If the lock file exists
if [ -e /tmp/$USER.foo.lock ]; then
    ## Check if the PID in the lockfile is a running instance
    ## of foo.sh to guard against crashed scripts
    if ps $(cat /tmp/$USER.foo.lock) | grep foo.sh >/dev/null; then
        echo "Script foo.sh is already running, exiting"
        exit
    else
        echo "Lockfile contains a stale PID, continuing"
        rm /tmp/$USER.foo.lock 
    fi
fi
## Create the lockfile by printing the script's PID into it
echo $$ > /tmp/$USER.foo.lock

## Rest of the script here

## At the end, delete the lockfile
rm /tmp/$USER.foo.lock
12
ответ дан 23 November 2019 в 05:22

Можно использовать pgrep, fo находят, выполняется ли процесс определенным пользователем, и затем запустите процесс, уже не работая пользователем:

#!/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 November 2019 в 05:22

Попробуйте его этим отрывком:

#!/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, потому что это разветвилось бы в ту же именованную оболочку.

2
ответ дан 23 November 2019 в 05:22

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

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

'команда' может быть любой командой удара или сценарием.

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

2
ответ дан 23 November 2019 в 05:22

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

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