I can use both ini_set('memory_limit', '512M'); in the file and php -d memory_limit=512M from the command line, but can also trace memory usage from terminal?
I know I can use memory_get_usage() inside a PHP file, but how to trace it from the command line?
Try:
$ watch -n 5 'php -r "var_dump(memory_get_usage());"'
This will watch every 5 seconds the memory state
Or may be you can use the 'ps' tool:
$ ps -F -C php-cgi
Output:
UID PID PPID C SZ RSS PSR STIME TTY TIME CMD
http 10794 10786 0 4073 228 0 Jun09 ? 00:00:00 /usr/bin/php-cgi
RSS is the Real-memory (resident set) size in kilobytes of the process.
The solution I was looking for with a simple output is
watch -n 5 'php -r "echo (string) memory_get_usage(true)/pow(10, 6);"'
Will return how many MB the PHP process is using.
2.097152
NOTICE: Solution like ps -F -C php-cgi on macOS machines will fail with
ps: illegal option -- F
Related
I run FFmpeg on my server using PHP exec().
It currently uses 100% of the cpu thread while encoding.
I followed this gude that uses a program called cpulimit to reduce it to 30%.
PHP
$args = "nice -19 cpulimit -l 30 -- ffmpeg -y -i intput.avi -vcodec libx264 -acodec aac -b:a 192k -threads 1 output.mp4"
exec(escapeshellcmd($args));
FFmpeg/PHP works, and it will work with nice/cpulimit through the terminal, but after adding
nice -19 cpulimit -l 30 -- to the PHP script it no longer works with exec().
Output
FFmpeg output returns blank. I'm not able to see the full output, I tried using:
$output = shell_exec($args);
echo "<p>$output</p>"
and
file_put_contents("/var/www/mysite/logs/$output.log", $line . PHP_EOL, FILE_APPEND);
But they return 1 empty line.
Solution
My thought is that www-data runs FFmpeg and nice/cpulimit may need root?
How can I get PHP exec() to work with FFmpeg args and cpulimit?
Or is there an alternative way to limit the usage %?
If safemode is enabled then, the execution of programes are limited. Check this documentation here, http://php.net/manual/en/function.exec.php
I found the answer on this forum post using google translate.
https://murobbs.muropaketti.com/threads/nice-komento-ja-php-n-exec-funktio-ratkaistu.551174/
Define the path to FFmpeg if using nice or cpulimit
nice -19 cpulimit -l 30 /usr/local/bin/ffmpeg -i ...
Now it works through PHP exec().
This is pretty weird, and I searched and tried everything, but I think I'm just making a dumb syntax error here.
I'm trying to run a stress test on the CPU , then immediately limit it's cpu usage to 30% , all this via PHP. The test is also run under another user and with a specified name so it can be limited. The stress test starts fine, but I can see the PHP file still loading, and it ends the second the stress test ends.
Here's some of the ways I tried doing it
$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"');
The whole purpose of this is because I am writing a script for a game hosting website, and I want to limit the resource consumption of each server to improve quality and not let someone hog all the resources.
Basically, instead of the stress test, a game server will run.
edit::
here's what I have now:
I need to run the stress under "test" , but the cpulimit under either sudo apache or root, because it requires special permissions. The stress still starts fine but it eats 99.9%
passthru('sudo runuser -l test -c "exec -a MyUniqueProcessName stress -c 1 -t 60s &" & sudo cpulimit -e MyUniqueProcessName -l 30 -i -z');
I can't see the cpulimit in the process list after doing this http://i.imgur.com/iK2nL43.png
Unfortunately, the && does more or less the opposite of what you want. :-) When you do A && B in Bash, that means, "Run command A and wait until it's done; if it succeeded, then run command B."
By contrast, A & B means, "Run command A and then immediately run command B."
So you're close to right in your command, but just getting tripped up by using two bash commands (should only need one) and the &&.
Also, did you try running each command separately, outside PHP, in two terminals? I just downloaded and built both stress and cpulimit (I assume these are the ones you're using?), ran the commands separately, and spotted a problem: cpulimit still isn't limiting the percentage.
Looking at the docs for stress, I see it works by forking child processes, so the one you're trying to CPU-limit is the parent, but that's not the one using the CPU. cpulimit --help reveals there's option -i, which includes child processes in what is limited.
This gets me to the point of being able to enter this in one terminal (first line shows input at the prompt; subsequent show output):
$> 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
Then, in another terminal running top, I see:
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
Much better. (Notice that outside the Bash shell where you aliased it with exec -a, you will see the process name as stress.) Unfortunately, I also see another issue, which is cpulimit remaining "listening" for more processes with that name. Back to cpulimit --help, which reveals the -z option.
Just to reduce the complexity a bit, you could leave the alias off and use the PID of the stress process, via the special Bash variable $!, which refers to the PID of the last process launched. Running the following in a terminal seems to do everything you want:
stress -c 1 -t 60s & cpulimit -p $! -l 30 -i -z
So now, just change the PHP script with what we've learned:
exec('bash -c "exec -a MyUniqueProcessName stress -c 1 -t 60s & cpulimit -e MyUniqueProcessName -l 30 -i -z"');
...or, simpler version:
exec('bash -c "stress -c 1 -t 60s & cpulimit -p \$! -l 30 -i -z"');
(Notice the $ in the $! had to be escaped with a backslash, \$!, because of the way it's quoted when passed to bash -c.)
Final Answer:
Based on the last example you amended to your question, you'll want something like this:
passthru('bash -c "sudo -u test stress -c 1 -t 60s & sudo -u root cpulimit -p \$! -l 30 -i -z"');
When I run this with php stackoverflow-question.php, it outputs the following:
stress: info: [3374] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: info: [3374] successful run completed in 60s
Process 3371 found
(The second two lines only appear after the PHP script finishes, so don't be mislead. Use top to check.)
Running top in another terminal during the 60 seconds the PHP script is running, I see:
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
This is exactly what you've described wanting: stress is running under the user test, and cpulimit is running under the user root (both of which you can change in the command, if desired). stress is limited to around 30%.
I'm not familiar with runuser and don't see the applicability, since sudo is the standard way to run a process as another user. To get this to work, you may have to adjust your settings in /etc/sudoers (which will require root access, but you obviously already have that). That's entirely outside the scope of this discussion, but as an example, I added the following rules:
my-user ALL=(test) NOPASSWD:NOEXEC: /home/my-user/development/stackoverflow/stress
my-user ALL=(root) NOPASSWD:NOEXEC: /home/my-user/development/stackoverflow/cpulimit
I am developing some PHP scripts on a Namecheap shared server. I accidentally made a loop which seems to go on indefinitely (or for a very long time), so now I am trying to kill it using SSH.
I have viewed a list of running processes with top, found the misbehaving PHP script, and tried to kill it with kill. However, after I kill it with this command, when I try using the ps, it is still running!
The result of the ps:
PID TTY STAT TIME COMMAND
819520 ? S 0:00 /usr/bin/php /my/php/file.php
I have tried killing the process over and over, but it just won't die!
The SSH is limited, so I can't use commands like killall. What do I do??!
To kill the process you can do the following:
Get the PID with ps -ef
kill it with kill -9 <pid>
A nice reference: When should I use kill -9?
Just for fun, an example:
$ sleep 100 &
[1] 4156
$ ps -ef | grep slee[p]
me 4156 3501 0 10:34 pts/5 00:00:00 sleep 100
$ kill 4156
[1]+ Terminated sleep 100
$ ps -ef | grep slee[p]
$
You can use 'ps' (process status) to get the ID and then use 'kill' to stop it.
http://linux.about.com/library/cmd/blcmdl_kill.htm
try this command. this will stop file from executing.
pkill -f /my/php/file.php
I need to manage the recording/capture of a website mindwhile it is running a slide-show to get videos form these slides.
My approach is:
<?php
define('FFMPEG_LIBRARY', '/usr/bin/ffmpeg ');
$ffmpegcmd = "ffmpeg -f x11grab -r 25 -s 800x600 -i :0.0 /tmp/output.mpg";
shell_exec($ffmpegcmd);
?>
But i get this error from php error log:
[x11grab # 0x81e8aa0] device: :0.0 -> display: :0.0 x: 0 y: 0 width: 800 height: 600
No protocol specified
No protocol specified
[x11grab # 0x81e8aa0] Could not open X display.
:0.0: Input/output error
Similar command from console run good.
Please, any help to get display and be able to control ffmpeg from browser php script?
Thanks in advance.
thanks for your time.
I got rid the X display error, but not I still haven't got the capture.
Using xvfb I get an unknown file at /tmp written by www-data user:
-rw-r--r-- 1 www-data www-data 11252 Sep 12 09:49 server-B20D7FC79C7F597315E3E501AEF10E0D866E8E92.xkm
Running startx I got also an unknown file at /tmp
-rw------- 1 www-data www-data 59 Sep 12 09:53 serverauth.oLcFlG7tXC
any of both grow in size so it is not capturing anything. The content is some binary thing.
What are those files about?
What I am trying is to write a script in which I can control the time ffmpeg is capturing the desktop to create a video from a jquery slide displayed on a website.
My try from console is closer, but if I can do it by browser I will be able to know when to stop sending an AJAX request once the slide is finished.
This is my try from console:
#!/bin/bash
# start the slide website: I will need to change it to control by querystring the language and course level
firefox http://www.languagecourse.net/vocabulary-trainer.php &
# start recording: I will need to adjust the frame to capture
ffmpeg -f x11grab -r 25 -s 800x600 -i :0.0 /tmp/output2.mpg &
# since I can't control the time a course takes I pause an arbitrary time
sleep 5
# look for the capture PID and close it
for i in $(ps aux | grep ffmpeg | sed "s/ */#/g" | cut -f2 -d#)
do
echo "proceso $i killed"
kill -9 $i
done
I wonder once the website is opened I can continue doing the control from AJAX, but not know if I will be able to get the ffmpeg PID to stop the command.
I will appreciate any kind of comments.
Regards,
ยท_-
You can use Xvfb to emulate a x-environment
<?php
$ffmpegcmd = "xvfb-run -a ffmpeg -f x11grab -r 25 -s 800x600 -i :0.0 /tmp/output.mpg";
shell_exec($ffmpegcmd);
or something like this
<?php
$ffmpegcmd = "startx -- `which Xvfb` :1 -screen 0 800x600x24 && DISPLAY=:1 && ffmpeg -f x11grab -r 25 -s 800x600 -i :0.0 /tmp/output.mpg");
shell_exec($ffmpegcmd);
That should be good to get rid of the "Could not open X display." error, and will probably solve your problem.
I am using FFMpeg to covert videos and it is working fine from the command line. I am using the following command:
ffmpeg -i input.mpg -vcodec libx264 -b 819200 -s 100x100 -g 15 -bf 3 -b_strategy 1 -coder 1 -qmin 10 -qmax 51 -sc_threshold 40 -flags +loop -cmp +chroma -me_range 16 -me_method hex -subq 5 -i_qfactor 0.71 -qcomp 0.6 -qdiff 4 -directpred 1 -flags2 +fastpskip -dts_delta_threshold 1 -acodec libfaac -ab 48000 output.m4v
However, when I run the command using PHP exec(), the output video is not encoded correctly and is distorted and cropped. I am using the following in PHP:
$output = exec($cmd . ' 2>&1', $output, $return);
The $output returns a '0' successful code.
Does any one have any suggestions?
Thank you.
This is unusual. It is possible that you have more than one ffmpeg binary installed, and the one that is being called by the PHP/Apache user is not the same as the one you call as your user from the command line.
Try specifying the full path to your ffmpeg binary (/usr/bin/ffmpeg or whatever) inside your exec().
It sounds like some command line options are getting lost/altered. I would try to split this into a 2 part process:
write a shell script on-the-fly (from PHP) that has all the proper command arguments (make it executable)
execute the shell script (from PHP)
I would probably try:
1) change ' 2>&1' to ' 2>&1 &'
Also, transcoding can take a while. Are you certain you are waiting long enough for the transcode to complete?