I have been scouring the forums to find out how you can allow a command / process to be ran by a user that is normally only permitted by root or itself.
There are some good resources out there but none are helping me in my instance, I am hopeful one of the Ubuntu genii can point me in the right direction.
I have installed cpulimit with apt-get install cpulimit, a package that adds the ability to limit cpu usage by a particular process. Once installed I can see the installation in /usr/bin/cpulimit.
I now must run cpulimit while running a process handled by the user, within that processes code.
I have added a couple attempts into my visudo file, all variations of this:
{USER} ALL=(ALL:ALL) NOPASSWD:/usr/bin/cpulimit
However, when I run the command (limit = percentage):
cpulimit --pid 159845 --limit 60
The response is:
Error: Process 159845 detected, but you don't have permission to control it.
Where 159845 is the correct process, it is mysqld.
I can run top -i and see that the process is ran by the user mysql:
PID | USER | PR | NI | VIRT | RES | SHR | S | %CPU | %MEM | TIME+ | COMMAND |
---|---|---|---|---|---|---|---|---|---|---|---|
159845 | mysql | 20 | 0 | 1460764 | 608076 | 3772 | S | 15.6 | 29.9 | 862:34.15 | mysqld |
This leads me to think there is no need to add the initial visudo line permitting the {USER} to run cpulimit, but more so that when {USER} runs cpulimit while targeting the process in question 159845 it is not allowed as {USER} doesn't have permission to touch mysql's processes.
How can I as {USER} run cpulimit on mysql's process mysql?
GENERIC: How to run a command as {USER} on a process owned by a different 'user / account / role'?
EDIT: The command is being ran within a script triggered within the crontab of {USER}.
EDIT 2: After running the command as sudo like so:
$limit_mysqld_cpu_usage = "sudo -u mysql cpulimit --pid " . $mysqld_id_exe_output[0] . " --limit " . $cpu_limit_as_perc_of_cpus;// Run commandexec($limit_mysqld_cpu_usage, $limit_mysqld_cpu_usage_output, $limit_mysqld_cpu_usage_id);
The script seems to freeze, where previously it would go on to continue with the script. The script past this point is tried and tested to be working very well without triggering the above command.
Q: Why does this not execute and then continue with the rest of the script?
A: Because the command runs and it begins watching over that process, preventing it from progressing through the code as we are expecting a return, so it will hang here forever.
Q: How can I trigger the exec() of the cpulimit command in the background or without the need to watch and wait for a response before continuing?
A: If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.
http://php.net/manual/en/function.exec.php
So essentially we need to > to another space such as /dev/null and run the process in the background by appending an &. In my case the command will need to look like this:
sudo -u {USER} cpulimit --pid {ID} --limit 60 > /dev/null &"
I have also switched exec() out in place of shell_exec() which seemingly doesn't require all the parameters or generate as heavy a response:
shell_exec(sudo -u {USER} cpulimit --pid {ID} --limit 60 > /dev/null &");