Это довольно странно, и я искал и пробовал все, но я думаю, что я просто делаю глупую синтаксическую ошибку здесь.
Я пытаюсь запустить стресс-тест на процессоре, а затем сразу ограничить его использование процессора до 30%, и все это через PHP. Тест также запускается под другим пользователем и с указанным именем, поэтому его можно ограничить. Стресс-тест начинается нормально, но я вижу, что файл PHP все еще загружается, и он заканчивается, как только заканчивается стресс-тест.
Вот несколько способов, которыми я пытался это сделать.
$output = exec('sudo runuser -l test -c "exec -a MyUniqueProcessName stress -c 1 -t 60s & cpulimit -e MyUniqueProcessName -l 30"');
$output = exec('sudo runuser -l test -c "exec -a MyUniqueProcessName stress -c 1 -t 60s > /dev/null & cpulimit -e MyUniqueProcessName -l 30"');
Основная цель этого заключается в том, что я пишу сценарий для веб-сайта игрового хостинга и хочу ограничить потребление ресурсов каждым сервером для повышения качества, а не для того, чтобы кто-то занимал все ресурсы.
По сути, вместо стресс-теста будет запущен игровой сервер.
редактировать::
вот что у меня сейчас:
Мне нужно запустить стресс под «test», но cpulimit под sudo apache или root, потому что он требует специальных разрешений. Стресс все еще начинается нормально, но съедает 99,9%
passthru('sudo runuser -l test -c "exec -a MyUniqueProcessName stress -c 1 -t 60s &" & sudo cpulimit -e MyUniqueProcessName -l 30 -i -z');
Я не вижу cpulimit в списке процессов после выполнения этого http://i.imgur.com/iK2nL43.png
К сожалению, &&
делает более или менее противоположное тому, что вы хотите. 🙂 Когда вы делаете A && B
в Bash это означает: «Запустите команду A и подождите, пока она не будет выполнена; если это удалось, то запустите команду B.»
В отличие от A & B
означает «Выполнить команду A, а затем немедленно запустить команду B.»
Таким образом, вы почти правы в своей команде, но просто запутались, используя два bash
команды (должна быть только одна) и &&
,
Кроме того, вы пытались запустить каждую команду отдельно, вне PHP, в двух терминалах? Я только что скачал и собрал оба стресс а также CPULimit (Я предполагаю, что это те, которые вы используете?), Запустил команды отдельно и обнаружил проблему: cpulimit
все еще не ограничивает процент.
Глядя на документы для stress
Я вижу, что это работает путем разветвления дочерних процессов, поэтому тот, который вы пытаетесь ограничить ЦП, является родительским, но это не тот, который использует ЦП. cpulimit --help
показывает, что есть вариант -i
, который включает дочерние процессы в то, что ограничено.
Это приводит меня к тому, что я могу ввести это в одном терминале (первая строка показывает ввод в приглашении; последующий вывод вывода):
$> exec -a MyUniqueProcessName stress -c 1 -t 60s & cpulimit -e MyUniqueProcessName -l 30 -i
[1] 20229
MyUniqueProcessName: info: [20229] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
Process 20229 found
Затем в другом терминале работает top
, Я вижу:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
20237 stackov+ 20 0 7164 100 0 R 30.2 0.0 0:04.38 stress
Намного лучше. (Обратите внимание, что за пределами оболочки Bash, где вы добавили exec -a
, вы увидите имя процесса как stress
К сожалению, я также вижу другую проблему, которая cpulimit
оставаясь «слушающим» больше процессов с этим именем. Вернуться к cpulimit --help
, который раскрывает -z
вариант.
Чтобы немного уменьшить сложность, вы можете оставить псевдоним выключенным и использовать PID stress
обрабатывать, используя специальную переменную Bash $!
, который ссылается на PID последнего запущенного процесса. Запуск следующего в терминале, кажется, делает все, что вы хотите:
stress -c 1 -t 60s & cpulimit -p $! -l 30 -i -z
Так что теперь, просто измените скрипт PHP на то, что мы узнали:
exec('bash -c "exec -a MyUniqueProcessName stress -c 1 -t 60s & cpulimit -e MyUniqueProcessName -l 30 -i -z"');
…или, более простая версия:
exec('bash -c "stress -c 1 -t 60s & cpulimit -p \$! -l 30 -i -z"');
(Обратите внимание на $ в $!
пришлось избежать обратной косой черты, \$!
из-за того, как он цитируется при передаче bash -c
.)
Окончательный ответ:
Основываясь на последнем примере, который вы внесли в свой вопрос, вы захотите что-то вроде этого:
passthru('bash -c "sudo -u test stress -c 1 -t 60s & sudo -u root cpulimit -p \$! -l 30 -i -z"');
Когда я запускаю это с php stackoverflow-question.php
, он выводит следующее:
stress: info: [3374] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: info: [3374] successful run completed in 60s
Process 3371 found
(Вторые две строки только появляются после завершения PHP-скрипта, так что не вводите в заблуждение. использование top
Проверять.)
Бег top
в другом терминале в течение 60 секунд работает скрипт PHP, я вижу:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3472 test 20 0 7160 92 0 R 29.5 0.0 0:07.50 stress
3470 root 9 -11 4236 712 580 S 9.0 0.0 0:02.28 cpulimit
Это именно то, что вы описали, желая: stress
работает под пользователем test
, а также cpulimit
работает под пользователем root
(оба из которых вы можете изменить в команде, если это необходимо). stress
ограничено до 30%.
Я не знаком с runuser
и не вижу применимости, так как sudo
это стандартный способ запуска процесса от имени другого пользователя. Чтобы заставить это работать, вам, возможно, придется скорректировать ваши настройки в / etc / sudoers (для этого потребуется доступ с правами root, но у вас, очевидно, это уже есть). Это полностью выходит за рамки этого обсуждения, но в качестве примера я добавил следующие правила:
my-user ALL=(test) NOPASSWD:NOEXEC: /home/my-user/development/stackoverflow/stress
my-user ALL=(root) NOPASSWD:NOEXEC: /home/my-user/development/stackoverflow/cpulimit
Других решений пока нет …