Shell Script - убить все процессы по имени, кроме меня

Я буду исходить из того, что grub вообще не появился и что ваша система по-прежнему загружается только в Windows 10.

Если это так, я бы сначала проверил таблицу разделов, чтобы узнать, был ли диск разбит на разделы и Linux действительно установлен на нем или нет.

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

  • Вариант 1: Попробуйте переустановить Kali и не забудьте выбрать /dev/sda в качестве держателя для grub.
  • Вариант 2: chroot в уже установленную систему Linux и установите grub на ваш /dev/sda/
4
30.03.2019, 22:42
4 ответа
#!/bin/sh

term_handler () {
    if [ "$ok_to_exit" -eq 1 ]; then
        echo 'exiting'
        exit
    else
        echo 'refusing to exit'
    fi
}

trap term_handler TERM

ok_to_exit=0
pkill -f test.sh
ok_to_exit=1

while true; do
    echo 'working...'
    sleep 2
done

Этот сценарий (, более простая версия которого приведена ниже, )устанавливает обработчик сигнала, функцию term_handler, которая завершает сценарий при получении сигнала TERM, если ok_to_exitзначение переменной 1.

В теле скрипта есть цикл, имитирующий некоторую форму выполняемой работы. Важно то, что перед вызовомpkill(вы можете изменить это на команду killall), она устанавливает ok_to_exitна 0, а сразу после этого устанавливает ее на 1.

При отправке сигнала TERMвсем соответствующим процессам он сам получит сигнал, но откажется выходить. Любые другие соответствующие процессы, , если они не находятся в точно таком же состоянии (, что может произойти, если вы запускаете сценарий более одного раза одновременно ), завершатся.

При запуске этот скрипт будет выводить

refusing to exit
working...
working...
working...

Когда запускается другая копия скрипта, он выводит exitingи затем завершается.

Упрощенная версия того же скрипта:

#!/bin/sh

trap '' TERM
pkill -f test.sh
trap - TERM

while true; do
    echo 'working...'
    sleep 2
done

Это просто игнорирует сигнал TERMво время вызова pkill, а затем восстанавливает обработчик сигнала по умолчанию перед продолжением.

1
27.01.2020, 20:54

Хороший способ не экспериментировать с обработчиками сигналов — подавать сигнал всем процессам, кроме себя:

for pid in $(pgrep ${0##*/}); do
    if [[ $pid -ne $$ ]]; then
        kill -s TERM $pid
    fi
done

Если вы плохо знакомы с bash, ${0##*/}дает вам базовое имя $0, имя вызова вашего скрипта, так что «/path/to/test.sh» становится «test.sh».

1
27.01.2020, 20:54

Если все ваши исполнения test.sh  всегда проходят такую ​​проверку сторожевой защиты, тогда вы можете просто:

pid=$(pgrep -o -f "/test.sh( |$)") && [ ${pid} -ne ${$} ] && kill $pid

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

Но на всякий случай, если вы хотите быть абсолютно уверены, что никакие предыдущие выполнения никогда не пропускали проверку, вы можете поместить приведенную выше строку в цикл while, например:

while pid=$(pgrep -o -f "/test.sh( |$)") && [ ${pid} -ne ${$} ] ; do
    kill $pid
done

Вышеприведенное убивает любые предыдущие выполнения test.sh, как бы они ни вызывались.

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

Вы можете сделать это, заключив любые аргументы, которые хотите проверить, в двойные -кавычки,вот так:

(примечание :Я показываю только часть pgrepдля использования в приведенном выше коде)

pgrep -o -f "/test.sh +arg1 +arg2 *$"

Дополнительные +и *$ должны совпадать не больше и не меньше, чем эти точные аргументы.(В этом примере литеральные строки arg1иarg2).

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

pgrep -o -f "/test.sh +${*} *$"

Здесь ${*}переводится во все аргументы текущего выполнения.

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

1
27.01.2020, 20:54

У вас могут возникнуть проблемы с запуском более двух экземпляров, но вы можете использовать pgrep/ pkillвот так:

#!/bin/sh

while [ "$(pgrep -c -f test.sh)" -gt 1 ]
do
  pkill --oldest -f test.sh
done

# rest of your script

Настройте параметр "test.sh", чтобы он более точно соответствовал имени самого процесса!

Для примера:

/bin/sh./test.sh

или

/bin/sh /full/path/to/test.sh

или

/bin/bash./test.sh

или

sh test.sh

... чтобы случайно не сопоставить что-то еще.

1
27.01.2020, 20:54

Теги

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