
通常は root またはそれ自身によってのみ許可されるコマンド/プロセスをユーザーが実行できるようにする方法を見つけるために、フォーラムを徹底的に調べてきました。
世の中には良いリソースがいくつかありますが、私の場合、どれも役に立ちません。Ubuntu の天才の誰かが正しい方向を指し示してくれることを期待しています。
apt-get install cpulimit を使用して cpulimit をインストールしました。これは、特定のプロセスによる CPU 使用量を制限する機能を追加するパッケージです。インストールが完了すると、/usr/bin/cpulimit にインストール内容が表示されます。
ユーザーが処理するプロセスの実行中に、そのプロセス コード内で cpulimit を実行する必要があります。
私は visudo ファイルにいくつかの試行を追加しました。すべてこれのバリエーションです:
{USER} ALL=(ALL:ALL) NOPASSWD:/usr/bin/cpulimit
ただし、コマンド (limit = percentage) を実行すると、次のようになります。
cpulimit --pid 159845 --limit 60
応答は次のとおりです。
Error: Process 159845 detected, but you don't have permission to control it.
159845 が正しいプロセスである場合、それは mysqld です。
top -i を実行すると、プロセスがユーザー mysql によって実行されていることがわかります。
ピッド | ユーザー | 広報 | ニ | バーチャル | RES | シュール | ス | %CPU | %メモリ | タイム+ | 指示 |
---|---|---|---|---|---|---|---|---|---|---|---|
159845 | マイスク | 20 | 0 | 1460764 | 608076 | 3772 | ス | 15.6 | 29.9 | 862:34.15 | マイSQL |
これにより、{USER} が cpulimit を実行できるようにする最初の visudo 行を追加する必要はないと考えられますが、{USER} が、問題 159845 のプロセスを対象にして cpulimit を実行する場合、{USER} には mysql のプロセスにアクセスする権限がないため、実行は許可されません。
{USER} として、mysql のプロセス mysql で cpulimit を実行するにはどうすればよいですか?
一般: 別の「ユーザー/アカウント/ロール」が所有するプロセスで {USER} としてコマンドを実行するにはどうすればよいでしょうか?
編集: コマンドは、{USER} の crontab 内でトリガーされたスクリプト内で実行されています。
編集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);
スクリプトはフリーズしているように見えますが、以前はスクリプトを続行していました。この時点以降のスクリプトは、上記のコマンドをトリガーすることなく、非常にうまく動作することがテスト済みです。
Q: なぜこれが実行されず、スクリプトの残りの部分が続行されないのですか?
A: コマンドが実行され、そのプロセスの監視が開始されるため、戻りを期待しているためにコードが進行できず、ここで永久にハングすることになります。
Q: cpulimit コマンドの exec() をバックグラウンドでトリガーするには、または続行する前に応答を監視して待機する必要なくトリガーするには、どうすればよいですか?
答え:この関数を使用してプログラムを起動した場合、バックグラウンドで実行を継続するには、プログラムの出力をファイルまたは別の出力ストリームにリダイレクトする必要があります。これを行わないと、プログラムの実行が終了するまで PHP がハングします。
http://php.net/manual/en/function.exec.php
したがって、基本的には、/dev/null などの別のスペースに > して、& を追加することでプロセスをバックグラウンドで実行する必要があります。私の場合、コマンドは次のようになります。
sudo -u {ユーザー} cpulimit --pid {ID} --limit 60 > /dev/null &"
また、すべてのパラメータを必要としないか、それほど重い応答を生成しないと思われる shell_exec() の代わりに exec() を使用しました。
shell_exec(sudo -u {USER} cpulimit --pid {ID} --limit 60 > /dev/null &");
答え1
@steeldriver の助けを借りて、問題の解決策を見つけました。
時系列順に答えると次のようになります。
別の「ユーザー/アカウント/ロール」が所有するプロセスで {USER} としてコマンドを実行するにはどうすればよいですか?
{USER} として動作しながら {ALTERNATIVE_USER} でプロセスを実行するには、sudo を使用する必要があります。これにより、次のように、コマンドを実行するユーザーを正確に指定できます。
sudo -u {ALTERNATIVE_USER} {COMMAND}
現在のスクリプトを続行できるように、バックグラウンドで {COMMAND} を実行するにはどうすればよいでしょうか?
プロセスがトリガーされるとスクリプトはフリーズしているように見えますが、実際にはフリーズしておらず、単に新しくトリガーされたコマンドが終了するのを待っているだけです。スクリプトは最初にトリガーされたプロセスに基づいて動作しているため、そのプロセスが終了することはありません。
これを実行するには、ハングするコマンドを開始するときに、ハングする場所となるアウトレットを指定する必要があります。これは、別の場所を指定することで実行できます。私の例では、 を使用しました> /dev/null
。
最後に、バックグラウンドで実行する必要がありましたが、これは . を追加することで実行できます&
。
最後に、特に私の場合は応答を受け取ることを望まず、単にコマンドを実行して指示どおりに実行してもらいたかったため、exec() を shell_exec() に置き換えました。
shell_exec(sudo -u {USER} cpulimit --pid {ID} --limit 60 /dev/null &");