Существует ли чистый способ `sudo pkill `без включения процесса `sudo `?

Это делается с помощью связанныхfaceSize1и т. д. ресурсов, упомянутых на странице руководства xterm .

5
12.04.2021, 00:12
3 ответа

Попробуйте:

sudo pkill -ef '/[p]erf record' | wc -l

Это трюк, в котором используется класс символов, содержащий только одну букву p.

Регулярное выражение ищет /perf, но в командной строке sudo pkillесть /[p]erf, что не совпадает.

Этот метод десятилетиями использовался в таких командах, какps aux | awk '/[f]oo/ {print $1}'

14
28.04.2021, 22:53

Обратите внимание, что шаблон в pkill/ pgrepявляется расширенным регулярным выражением, как и в grep -E. Следовательно, вы можете просто предоставить регулярное выражение, которое более точно нацелено на нужный процесс (es ). В вашем случае это может быть похоже на:

sudo pkill -ef '^(/[^/]+)+/perf record'

или даже лучше трюк, описанный @cas в его ответе.

Может быть, стоит пояснить, зачем все это нужно:

Хорошо известно, что pkill/ pgrepникогда не совпадают друг с другом. Однако критерии, которые они используют, заключаются в сопоставлении PID , т. е. они проверяют, является ли один из совпадающих PID их , и исключают именно его.

Но при запуске (с -fполной -командой -параметром линейного режима )через sudoкоманда pkillтакже соответствует sudoсобственному процессу, потому что он также содержит строку строки команды -, которая соответствует шаблону голого , подобному тому, который вы использовали. Очевидно, что собственный процесс sudoне имеет того же PID, что и процесс pkill, поэтому pkillне исключает его из списка, тем самым убивая процесс sudo, породивший (и все еще удерживающий )процесс. pkillпроцесс.

Рассмотрим:

$ sudo -b perf record sleep 1234
$ sudo pgrep -fa '/perf record'
1446 /usr/lib/linux-tools/4.2.0-42-generic/perf record sleep 1234
1466 sudo pgrep -fa /perf record  # <-- if I issued a pkill, this process, the sudo, would have been killed

В приведенном выше фрагменте обратите внимание на то, что собственный процесс pgrepдействительно исключен из списка. Но процесс sudoтакже содержит командную строку -, которая соответствует простому регулярному выражению.

Предоставляя вместо этого более специальное регулярное выражение, pkillбольше не включает процесс sudo pkill -ef <...>, поскольку собственная командная строка процесса, содержащая адаптированное регулярное выражение, не соответствует самому регулярному выражению.


Последнее замечание по опции -F.

В то время, когда я пишу это, эта опция по-прежнему считывает только один единственный PID из файла. Так что да, документация, а также вывод программы --helpвводят в заблуждение. Этот комментарий в источниках говорит безобразную правду.

/* FreeBSD: the arg is a file containing a PID to match */

6
28.04.2021, 22:53

Получить pid напрямую и не искать его:

pid="$(sudo bash -c 'sleep 100 >/dev/null & echo $!')"
sudo kill "$pid"

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

Основное преимущество здесь по сравнению с pkillзаключается в том, что вы всегда будете получать правильный pid вместо возможного уничтожения других процессов, соответствующих вашему запросу. Например, если вы запускаете свой сценарий много раз одновременно, может быть несколько perfпроцессов, которые будут соответствовать [p]erf record, каждый из которых является потомком каждого вызова сценария.

2
28.04.2021, 22:53

Теги

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