How to execute commands through PHP? - php

I am trying to convert videos into MP4 using FFMPEG. I have it set up this way:
.
.
private $ffmpegPath;
public function __construct($con) {
$this->con = $con;
$this->ffmpegPath = realpath("ffmpeg/bin/ffmpeg.exe");
}
.
.
public function convertVideoToMp4($tempFilePath, $finalFilePath){
$cmd = "$this->ffmpegPath -i $tempFilePath $finalFilePath 2>&1";
$outputLog = array();
exec($cmd, $outputLog, $returnCode);
if($returnCode != 0){
foreach ($outputLog as $line){
echo $line."<br>";
return false;
}
}
return true;
}
And in the browser i get the following error:
'C:\xampp\htdocs\Thinksmart First Sprint' is not recognized as an internal or external command".
In my constructor i have it set up to give me the realpath and i suspect that this is what it does in the command line:
C:/xampp/htdocs/Thinksmart FIrst Sprint/ffmpeg/bin/ffmpeg.exe -i (file temp name) (file name i want)
And this should work, but i dont know why it wont. Any ideas? Its my first time working with video conversions.

As you can see, spaces in your command are used to separate arguments. So if there are spaces in a path you need to quote the entire path with quotes so that the shell/processor knows they aren't separators but are one argument:
$cmd = $cmd = '"' . $this->ffmpegPath . '" -i $tempFilePath $finalFilePath 2>&1';
Which will result in a command something like this:
"C:/xampp/htdocs/Thinksmart First Sprint/ffmpeg/bin/ffmpeg.exe" -i C:/path/to/file1 C:/path/to/file2 2>&1
I think only double-quotes work on Windows. You need to quote $tempFilePath and $finalFilePath if they might have spaces in them as well.

Related

PHP in Windows: add an environment variable for User or Machine

I am trying to update the Path environment variable in Windows with a PHP script, but if I use putenv() it doesn't change. I can get the paths list in the Path variable but I am not able to update it.
Another problem is that if I use getenv('Path') to get the paths list, I have a unique string with all paths merged from the Path variable of User and of the Machine.
I'm wondering if there is a better way to do that, maybe acting directly in the registry key to update User Path variable.
UPDATE
I think I found out a half-solution, but it doesn't work as expected.
What do I want to do?
I just want to make a script that allow me to switch from a PHP version to another changing the Path variable.
I made the script, it seems to work and the Path variable is successfully updated, but even if I close and reopen the cmd prompt if I type php -v it doesn't seems to get the updated var. If I open the Environment Variables windows, then open the "Path" variable and click on Ok and Ok again, then the refresh is got but the cmd prompt.
This is very strange to me, and if I have to do this everytime, then script loose its benefit...
I recorded a video, I hope it explain the problem better than my English...
https://1drv.ms/v/s!Ao2s4w8xSxBSh7RY4y5pB8u1g_QFSQ
This is the code of the script:
// Load PHP available versions
$laragon_php_paths = 'D:\www-servers\laragon\bin\php';
$php_paths = scandir($laragon_php_paths);
$path_var_name = "Path";
// Backup before doing a disaster
$date = new DateTime();
exec('REG EXPORT HKCU\Environment BackupUserEnvironment_' . $date->format('YmdHisv') . '.reg');
// Load registry key of user's Path environment variable
exec('REG QUERY HKCU\Environment /v ' . $path_var_name, $output, $result);
$path = explode(' ', $output[2]);
$path_array = explode(';', $path[count($path) - 1]);
// Get the current PHP Version and get the key of the item of the PHP bin path
foreach ($path_array as $key => $path_item) {
if (strpos($path_item, $laragon_php_paths) !== false) {
$the_key = $key;
$current_php_version = substr($path_item, strrpos($path_item, '\\') + 1);
}
}
echo 'Available PHP versions:' . PHP_EOL . PHP_EOL;
$i = 0;
foreach ($php_paths as $dir) {
if ($dir === '.' || $dir === '..') continue;
echo ' [' . ++$i . '] ' . $dir;
if ($dir === $current_php_version) {
echo ' [Current version]';
}
echo PHP_EOL;
}
// Get file descriptor for stdin
echo PHP_EOL;
echo 'Select a PHP version: ';
$fd = fopen('php://stdin', 'r');
$choice = (int) fgets($fd);
echo PHP_EOL;
// Check if choice is between 1 and number of choices
if ($choice > 0 && $choice <= $i) {
// Change the original php version with the new one
$new_php_version = $php_paths[$choice + 1];
$path_array[$the_key] = $laragon_php_paths . '\\' . $new_php_version;
echo 'PHP version changed to: ' . $new_php_version . PHP_EOL;
} else {
echo 'No allowed choice, nothing changed.';
echo PHP_EOL;
}
// Escape some chars for cmd
$new_path_var = str_replace(['%', ' '], ['^%', '" "'], implode(';', $path_array));
$cmd = 'REG ADD HKCU\Environment /f /t REG_EXPAND_SZ /v ' . $path_var_name . ' /d ' . $new_path_var;
// Execute
exec($cmd);

Running commands from PHP exec shows different result than from shell

The PHP exec command is not executing the same as the shell's interaction.
cd /var/www/myfolder
zip -r /var/www/myfolder/temp/newfile.zip ./*
generates just a zip of files in the temp directory. However (simplified version):
$zip_dir = '/var/www/myfolder';
$temp_dir = $zip_dir . '/temp/';
chdir($zip_dir);
exec('zip -r ' . $temp_dir . 'newfile.zip ./*', $return);
generates the same zip but with the full path's of var and www (which results in two copies of myfolder so my file is twice as large as needed). The $return however has the same output as the command line execution. Both state only 15 files directories/folders were zipped. There is no mention of var or www in the PHP output.
I believe the chdir() command will not have any bearing on how the commands in exec() are run. So this might fix it:
$zip_dir = '/var/www/myfolder';
$temp_dir = $zip_dir . '/temp/';
$cmd = 'cd ' . escapeshellarg($zip_dir) . ' && zip -r ' . escapeshellarg($temp_dir . 'newfile.zip') . ' ./*';
exec($cmd, $return);
Note we always escape variables being passed to the command line.
But why not just zip within PHP?
<?php
$zip_target = "/var/www/myfolder";
$zip_file = "/var/www/myfolder/temp/newfile.zip";
$zip_temp = tempnam(sys_get_temp_dir(), 'a458');
$zip_obj = new \ZipArchive();
if ($zip_obj->open($zip_temp, ZIPARCHIVE::OVERWRITE)) {
$zip_obj->addGlob("$zip_target/**/*.*");
}
$zip_obj->close();
rename($zip_temp, $zip_file);

PHP: mysqldump: Couldn't find table: ">"

I tried to make simple php script to backup databes using mysqldump but i got this error:
mysqldump: Couldn't find table: ">"
And this is the function that i have write to make the job:
protected function dump($params, $dbs, $backup_folder)
{
if (!is_writable($backup_folder)) {
throw new Exception(sprintf('The backup folder is not writable: %s',
$backup_folder));
}
$backup_folder = trim($backup_folder, "/"); // be sure that there is no / at the end
$baseCmd = 'mysqldump --hex-blob --routines --skip-lock-tables -h%s -u%s -p%s %s > %s';
foreach ($dbs as $db) {
$dest = sprintf('%s/%s', $backup_folder,
$db . '_' . date('YmdHis') . '.sql');
$cmd = sprintf($baseCmd, $params['host'], $params['user'],
$params['password'], $db, $dest);
echo "Exec: $cmd: ";
$last = system(escapeshellcmd($cmd), $res);
echo $res;
if ( 0 !== $res) {
echo "Fail";
} else {
echo "Done \n";
}
}
}
The command printed by this function give:
mysqldump --hex-blob --routines --skip-lock-tables -hdb-backup -uroot -pMyPwd my_db_name > backups/my_db_name_20151010232734.sql
When i execute this command from Shell it works very well but not from Php script.
My config is:
My Desktop System Shell: Ubuntu 15.04
Mysql Server: Mysql 5.6 installed in Ubuntu Server 15.04
PHP version: 5.6.4
Any help ?
Thank you
The escapeshellcmd() command prepends a \ to the >.
From the PHP documentation:
Following characters are preceded by a backslash: #&;`|*?~<>^()[]{}$\, \x0A and \xFF.
You should either escape each argument individually with escapeshellarg(), or ensure that your method arguments ($params, $db, and $backup_folder) are valid and don't contain one of those chars and just use
system($cmd, $res)
I hope this helps!

Why I'm getting "sh" calling "echo $0" inside bash inside php exec?

I have code like this:
public function shell($code) {
$code = preg_replace('/"/', '\\"', $code);
exec('bash -c "' . $code . '"', $result);
return $result;
}
and when I call shell("echo $0"); I'm getting sh instead of bash, why?
The original shell is expanding the variable inside doublequotes. To prevent variable expansion, use single quotes:
exec("bash -c '" . $code . "'", $result);

Filesize 0 mysqldump

I am using Windows 7 and using php i am backing up my database with the help of mysqldump. The file gets successfully written but the size remains always 0. Any idea why is this happening?
Note :- If i type the same command in command line, it works. This is my function :-
public static function BackupDatabase($backupPath){
$fileName = uniqid() .'.sql';
$backupCommand = 'mysqldump -u ' . DBUsername .' -p' . DBPassword .' abc >' . $backupPath . $fileName ;
$retVal = '';
$feedback = system($backupCommand, $retVal);
if($feedback == NULL || $feedback == '')
return 'Database backed up successfully by name ' . $fileName;
else
return $feedback;
}
EDIT :-
public static function BackupDatabase($backupPath){
$fileName = uniqid() .'.sql';
$backupCommand = 'mysqldump -u ' . DBUsername . ' abc > ' . $backupPath . $fileName .' 2>&1' ;
echo $backupCommand;
$retVal = '';
$feedback = system($backupCommand, $retVal);
echo $retVal;
if($feedback == NULL || $feedback == '')
return 'Database backed up successfully by name ' . $fileName;
else
return $feedback;
}
Thanks in advance :)
I believe is caused by the environment setting.
You can execute mysqldump successfully in the command line as you probably has mysqldump register in your environment.
While running in a PHP, the path to mysqldump might not recognized by user that running the web server.
And
$feedback = system('unknown program > file', $retval);
Will always set $feeback = ''; even PHP cannot find where is your mysqldump program, it still pipe a single character to backup file.
You can put in absolute path to mysqldump to test again.
Check your $backupCommand string. It seems to me that there are some spaces missing (e.g. in the vicinity of '-p').
After much headache, this syntax worked for me:
cmd /c " C:\mysqldump.exe -h $mysql_server -u $mysql_user --password=$mysql_password $dbname > C:\Dump.sql "

Categories