1

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 command
exec($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 &");
4
  • "when I run the command" - what command, exactly? Generically, you would use sudo, either sudo -u {USER} somecommand or sudo somecommand to run as root by default Sep 7, 2022 at 13:26
  • @steeldriver - Added the command, thank you for the guidance.
    – Doopz
    Sep 7, 2022 at 13:39
  • @steeldriver - I think this removes the error, and it seems to runnn from within the cronjob I have set up however once the line runs that command, it sees to freeze on the previous process that triggers the new process. I will create a new edit.
    – Doopz
    Sep 7, 2022 at 15:30
  • @user535733 Appreciate you're words however in this instance it is irrelevant, make up whatever cronjob you can think of that will be run as the user, imagine it attempting to run the command for another user. The less specific the question, the more people it will help in the long run. We are teaching people to fish here :)
    – Doopz
    Sep 7, 2022 at 16:22

1 Answer 1

0

I found the solution to my troubles with the assistance of @steeldriver.

To answer this in chronological order:

How to run a command as {USER} on a process owned by a different 'user / account / role'?

In order to run a process on an {ALTERNATIVE_USER} while acting as {USER}, we must make use of sudo, to which you can then specify which exact user should be running the command, like so:

sudo -u {ALTERNATIVE_USER} {COMMAND}

How can I trigger a {COMMAND} to run in the background allowing the current script to continue?

The script appears to freeze as the process is triggered, it is not frozen it is simply waiting for the newly triggered command to end, which it won't as it is acting on the initially triggered process, which will never reach its end.

To do this when we initiate the command that hangs, we must specify an outlet for it so it has somewhere to hang. This can be done by pointing to an alternative location, in my instance I used > /dev/null.

Lastly, what I needed to do was run it in the background, which can be done by appending an &.

Final point, specifically for me I did not wish to receive a response, I simply wanted the command to run off and do as I said, so I swapped out exec() in favour of shell_exec().

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.