У меня есть говорящие часы, использующие eSpeak.
В вашем случае может помочь, если вы добавите идентификатор пользователя, который должен воспроизводить звуки, в группу аудио (в конце строки, начинающейся с audio
, в файле /etc/group
).
Так что добавьте root
, если вы хотите, чтобы он воспроизводился через sudo crontab -e
. (Это было необходимо только для меня с обычными идентификаторами пользователей (, а не для root
), но это может отличаться в разных дистрибутивах Linux.)
Вы можете попробовать команду jobs
, чтобы проверить, было ли это задание прекращено или нет. Результат выглядит следующим образом:
➜ ~ vim test.txt &
[1] 5634
➜ ~
[1] + 5634 suspended (tty output) vim test.txt
➜ ~ jobs
[1] + suspended (tty output) vim test.txt
➜ ~ kill -9 5634
[1] + 5634 killed vim test.txt
➜ ~ jobs
➜ ~
В этом случае vim test.txt
находится во втором столбце и может использоваться для проверки того, что процесс остается прежним и программа является правильной. Если jobs
не возвращает целевую программу, вы можете изменить свою скрипт, чтобы не убить PID
.
Как было сказано в комментариях, утилита pkill
может оказаться полезной.
Поскольку вы говорите "скрипт bash", вам, скорее всего, придется запуститьpkill bash
-А этого делать не следует.
Вместо этого вы можете использовать pkill -f <name>
, который будет использовать полное имя процесса для соответствия. Итак, предполагая, что ваша задача bash /home/me/my_script.sh
, вы можете использовать следующее:
pkill -f -e my_script.sh
Параметр -e
является необязательным и просто выводит то, что было убито.
Альтернатива:
Сохраните следующий скрипт как/usr/bin/mykill
(или куда угодно):
#!/bin/bash
mypid="$1"
if [[ ! -f /proc/$mypid/cmdline ]]; then
echo "Process ID not found."
exit 1
else
echo "About to kill $(cat /proc/$mypid/cmdline)"
echo "Press enter if you want to kill that process"
read -p "Press CTRL-C if you don't want that"
kill $mypid
fi
И запустите какmykill <pid>
Надежного способа сделать это не существует.
Поскольку идентификаторы PID являются глобальными повторно используемыми идентификаторами, их использование по своей сути неприемлемо. Но то, как реализованы оболочки, делает это намного хуже, :оболочка пожинает плоды своих детей жадно , т.е. она вызывает системный вызов waitpid()
, как только они умерли, и сохраняет их PID и статус где-то в памяти.Фоновые задачи, запущенные как foo &
, НЕ задерживаются как процессы-зомби, пока вы не вызовете встроенную команду wait
. Возможно, PID уже использовался повторно, так как вы получили его с помощью команд jobs
или pgrep
.
Ваша лучшая надежда состоит в том, чтобы сократить временной интервал, в течение которого PID могут быть повторно использованы, и свести к минимуму риски. Как было предложено, вы можете использовать pkill
вместо явного уничтожения по PID. Особенно полезен его -P
флаг ("выбрать по родителю" ), отсюда
pkill -P "$$"
Если ваш фоновый процесс находится под вашим контролем, добавьте дополнительную идентификацию в его командную строку в виде метки, копию которой вы можете сохранить вместе с PID, а позже проверить в ps -o args myPid
.
Я использую такой вариант, как--unique "${myTag}"
Я получаю myTag либо из uuidgen
, либо из date
с точностью до наносекунд. Если это задание ssh, укажите локальное имя хоста.
Если вы не можете ввести новую опцию:
.. Используйте date +%s
, чтобы получить время начала задания и сохранить его вместе с Pid.
.. Используйте ps -o etimes
, чтобы получить прошедшее время процесса в секундах.
.. Сравните с текущим date +%s
(, вероятно, с допуском в несколько секунд ).
Любой метод в сочетании с PID должен иметь пренебрежимо малую вероятность ошибки.
Я не согласен с тем, что это вообще невозможно. И я бы не рекомендовал убивать по имени -с помощью pkill
, если вы можете этого избежать (что, если вы законно хотите, чтобы несколько экземпляров какой-либо команды имели индивидуальные тайм-ауты? ). Я не понимаю, как ответ относительно jobs
вообще что-то делает для устранения состояния гонки; с использованием jobs
, а затем kill
не является атомарным.
Тем не менее, мы можем использовать идентификаторы группы процессов(PGID
с ), если управление заданиями включено, или использовать подоболочку и уничтожить идентификатор родительского процесса (PPID
), если это невозможно. Смотрите мой пост здесь:https://unix.stackexchange.com/a/649320/464414
Я приведу только выдержку из предпочтительного метода и вставлю его сюда; см. сообщение выше для заметок и альтернатив.
ОБНОВЛЕНО :Версия ниже теперь работает с трубами
timeOut() {
checkArgs() { [ $(( ${1} )) -gt 0 -a "${*:2}" ]; }
jobControlEnabled() { expr "${-}" : '.*m' >/dev/null; }
terminalFDs() { [ -t 0 -a -t 1 ]; }
groupLeader() { sh -c 'expr `ps -o pgid= ${PPID}` : "${PPID}" >/dev/null;'; }
timeOutImpl() {
groupLeader || { echo "Job control error - not group leader!"; return -1; }
KILL_SUB="kill -- -`sh -c 'echo ${PPID}'`"
{ sleep ${1}; ${KILL_SUB}; } &
"${@:2}"; ${KILL_SUB}
}
checkArgs "${@}" || { echo "Usage: timeOut <delay> <command>"; return -1; }
if jobControlEnabled && terminalFDs; then
( timeOutImpl "${@}"; )
else
( set -m; ( timeOutImpl "${@}"; ); )
fi
}