Разрешение {USER} запускать команду для процесса, принадлежащего другому пользователю

Разрешение {USER} запускать команду для процесса, принадлежащего другому пользователю

Я просматривал форумы, чтобы узнать, как можно разрешить запуск команды/процесса пользователю, который обычно имеет право на это только root или он сам.

Есть несколько хороших ресурсов, но ни один из них не помог мне в моем случае. Я надеюсь, что кто-нибудь из гениев Ubuntu укажет мне правильное направление.

Я установил cpulimit с помощью apt-get install cpulimit, пакета, который добавляет возможность ограничивать использование процессора определенным процессом. После установки я могу увидеть установку в /usr/bin/cpulimit.

Теперь мне нужно запустить cpulimit во время выполнения процесса, управляемого пользователем, в коде этого процесса.

Я добавил пару попыток в свой файл visudo, все вариации этого:

{USER} ALL=(ALL:ALL) NOPASSWD:/usr/bin/cpulimit

Однако, когда я запускаю команду (предел = процент):

cpulimit --pid 159845 --limit 60

Ответ таков:

Error: Process 159845 detected, but you don't have permission to control it.

Правильный процесс 159845 — mysqld.

Я могу запустить top -i и увидеть, что процесс запущен пользователем mysql:

ПИД ПОЛЬЗОВАТЕЛЬ PR НИ ВИРТ РЕС ШР С %ПРОЦЕССОР %МЕМ ВРЕМЯ+ КОМАНДА
159845 mysql 20 0 1460764 608076 3772 С 15.6 29.9 862:34.15 mysqld

Это наводит меня на мысль, что нет необходимости добавлять начальную строку visudo, разрешающую {USER} запускать cpulimit, а тем более, что когда {USER} запускает cpulimit, обращаясь к процессу, указанному в вопросе 159845, это не разрешено, поскольку {USER} не имеет разрешения на доступ к процессам MySQL.

Как я могу как {USER} запустить cpulimit для процесса mysql?

GENERIC: Как запустить команду от имени {USER} в процессе, принадлежащем другому «пользователю/учетной записи/роли»?

РЕДАКТИРОВАТЬ: Команда выполняется в скрипте, запущенном в crontab пользователя {USER}.

ПРАВКА 2: После запуска команды как sudo, например так:

$limit_mysqld_cpu_usage = "sudo -u mysql cpulimit --pid " . $mysqld_id_exe_output[0] . " --limit " . $cpu_limit_as_perc_of_cpus;

// Run command
exec($limit_mysqld_cpu_usage, $limit_mysqld_cpu_usage_output, $limit_mysqld_cpu_usage_id);

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

В: Почему это не выполняется, а затем продолжается остальная часть скрипта?

A: Потому что команда запускается и начинает следить за этим процессом, не давая ему продвигаться по коду, поскольку мы ожидаем возврата, поэтому он зависнет здесь навсегда.

В: Как запустить exec() команды cpulimit в фоновом режиме или без необходимости наблюдать и ждать ответа перед продолжением?

А:Если программа запущена с помощью этой функции, то для продолжения ее работы в фоновом режиме вывод программы должен быть перенаправлен в файл или другой поток вывода. Если этого не сделать, PHP зависнет до тех пор, пока выполнение программы не завершится.

http://php.net/manual/en/function.exec.php

Итак, по сути, нам нужно перейти в другое пространство, например, /dev/null, и запустить процесс в фоновом режиме, добавив &. В моем случае команда должна выглядеть так:

sudo -u {ПОЛЬЗОВАТЕЛЬ} cpulimit --pid {ИДЕНТИФИКАТОР} --limit 60 > /dev/null &"

Я также заменил exec() на shell_exec(), который, по-видимому, не требует всех параметров и не генерирует такой тяжелый ответ:

shell_exec(sudo -u {USER} cpulimit --pid {ID} --limit 60 > /dev/null &");

решение1

Я нашел решение своих проблем с помощью @steeldriver.

Ответим на этот вопрос в хронологическом порядке:

Как выполнить команду от имени {USER} в процессе, принадлежащем другому «пользователю/учетной записи/роли»?

Чтобы запустить процесс на {ALTERNATIVE_USER}, действуя от имени {USER}, мы должны использовать sudo, с помощью которого вы затем можете указать, какой именно пользователь должен запустить команду, например так:

sudo -u {ALTERNATIVE_USER} {COMMAND}

Как запустить {КОМАНДУ} в фоновом режиме, чтобы текущий скрипт мог продолжить работу?

Скрипт, по-видимому, зависает при запуске процесса. На самом деле он не завис, а просто ждет завершения новой запущенной команды, чего не произойдет, поскольку он действует на изначально запущенный процесс, который никогда не достигнет своего завершения.

Чтобы сделать это, когда мы инициируем команду, которая зависает, мы должны указать для нее выход, чтобы ей было где зависнуть. Это можно сделать, указав на альтернативное местоположение, в моем случае я использовал > /dev/null.

Наконец, мне нужно было запустить его в фоновом режиме, что можно сделать, добавив &.

Последний момент: лично я не хотел получать ответ, я просто хотел, чтобы команда выполнилась и сделала то, что я сказал, поэтому я заменил exec() на shell_exec().

shell_exec(sudo -u {USER} cpulimit --pid {ID} --limit 60 /dev/null &");

Связанный контент