php shell exec acting different to running command directly - php

I have a php script that attempts to remove all files from a directory structure, but preserve everything in svn. I found this command online which does the job perfectly if you plug it directly in a shell
find /my/folder/path/ -path \'*/.svn\' -prune -o -type f -exec rm {} +
Unfortunately if I perform a shell_exec in php on that command like so:
$cmd = 'find $folderPath -path \'*/.svn\' -prune -o -type f -exec rm {} +';
shell_exec($cmd);
Then all the files in my current directory that I call the php script from are deleted as well.
Can someone explain why, and how to fix the issue so that I can fix the php script so it acts like expected, removing only those files in the specified folder
The full source code is below, just in case there is perhaps a silly mistake in there that I have missed:
<?php
# This script simply removes all files from a specified folder, that aren't directories or .svn
# files. It will see if a folder path was given as a cli parameter, and if not, ask the user if they
# want to remove the files in their current directory.
$execute = false;
if (isset($argv[1]))
{
$folderPath = $argv[1];
$execute = true;
}
else
{
$folderPath = getcwd();
$answer = readline("Remove all files but not folders or svn files in $folderPath (y/n)?" . PHP_EOL);
if ($answer == 'Y' || $answer == 'y')
{
$execute = true;
}
}
if ($execute)
{
# Strip out the last / if it was given by accident as this can cause deletion of wrong files
if (substr($folderPath, -1) != '/')
{
$folderPath .= "/";
}
print "Removing files from $folderPath" . PHP_EOL;
$cmd = 'find $folderPath -path \'*/.svn\' -prune -o -type f -exec rm {} +';
shell_exec($cmd);
}
else
{
print "Ok not bothering." . PHP_EOL;
}
print "Done" . PHP_EOL;
?>

Your command looks okay. At least in shell. If you would actually troubleshoot your issue in PHP with a simple
var_dump($cmd);
You would see where your error lies:
$cmd = 'find $folderPath -path \'*/.svn\' -prune -o -type f -exec rm {} +';
Look closely. Hint: A single can't make a double for a dollar.

It all comes down to:
$cmd = 'find $folderPath -path \'*/.svn\' -prune -o -type f -exec rm {} +';
shell_exec($cmd);
Since you are using single quotes the variable $folderPath is not changed. So you are executing
find $folderPath -path '*/.svn' -prune -o -type f -exec rm {} +
instead of
find /my/folder/path/ -path \'*/.svn\' -prune -o -type f -exec rm {} +
use double quotes or $cmd = 'find '.$folderPath.' -path \'*/.svn\' -prune -o -type f -exec rm {} +';

Related

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);

trying to create a ftp user with permissions

So I'm trying to create a ftp user and give him permissions to a specific directory, but the user is not being created. When I echo the commands the directory is created and the permissions are given to the user but when i try to log with the credentials created it's not working. Please take a look. What am I doing wrong ?
$randomNum = substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 8);
$randomPass = substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 6);
$src = $request->path;
$dest = "/home/$randomNum";
echo $ssh->exec("mkdir $dest\n");
echo $ssh->exec("useradd -m -d $dest $randomNum\n");
echo $ssh->exec("passwd $randomNum\n");
echo $ssh->read('New password:');
echo $ssh->write($randomPass."\n");
echo $ssh->exec("nice -n 19 cp -Rf $src $dest && chown -Rf $randomNum:$randomNum $dest && exit\n");
$ssh->disconnect();
Assuming that randomNum is the username, randomPass the password and dest the home directory,
Change this:
echo $ssh->exec("mkdir $dest\n");
echo $ssh->exec("useradd -m -d $dest $randomNum\n");
echo $ssh->exec("passwd $randomNum\n");
echo $ssh->read('New password:');
echo $ssh->write($randomPass."\n");
echo $ssh->exec("nice -n 19 cp -Rf $src $dest && chown -Rf $randomNum:$randomNum $dest && exit\n");
To this:
$ssh->exec("useradd -M " . $randomNum. " -d " . $dest);
$ssh->exec("echo \"" . $randomNum . ":" . $randomPass . "\" | sudo chpasswd");
$ssh->exec("chown -R " . $randomNum . ":" . $randomNum . " " . $dest);
From your code:
echo $ssh->exec("passwd $randomNum\n");
echo $ssh->read('New password:');
echo $ssh->write($randomPass."\n");
For that command, in particular, you'd need to enable PTY mode for the reads / writes to work. You can do so by doing $ssh->enablePTY() before the command. It might not be a bad idea to do $ssh->disablePTY() after the command, however.
Also, echo $ssh->write($randomPass."\n");... that's not really gonna have the desired effect. $ssh->write just returns true or false depending on the success or failure of the write command.

Touch a file as sudo

How can I touch a file as sudo when using [Symfony's Filesystem][1]?
So far I have:
$fs = new Filesystem();
$confFile = sprintf('/etc/apache2/sites-available/%s.conf', $input->getArgument('name'));
$fs->touch($confFile);
But this code fails with error: Permission denied.
[1]: http://symfony.com/doc/current/components/filesystem/introduction.html
From the Symfony Filesystem component:
public function touch($files, $time = null, $atime = null)
{
foreach ($this->toIterator($files) as $file) {
$touch = $time ? #touch($file, $time, $atime) : #touch($file);
if (true !== $touch) {
throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
}
}
}
As you see there, the touch() method is just a simple wrapper around PHP's buildin touch() function. If you need to run touch with elevated rights via sudo, you have to call it directly:
shell_exec('sudo touch ' . escapeshellarg($file));
you need to change the rights on /etc/apache2/sites-available/ to add write access to apache user
HTTPDUSER=`ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1`
sudo chmod +a "$HTTPDUSER allow delete,write,append,file_inherit,directory_inherit" /etc/apache2/sites-available/

PharData class fails when tar contents has relative paths

I'm having trouble with using Phar to access gzipped tar files.
Here's my test code:
<?php
function r($a) {
print " has " . count($a) . " files:\n";
foreach (new RecursiveIteratorIterator($a) as $path => $fileinfo) {
print " " . $path . "\n";
}
}
print "\n1.tgz";
r(new PharData('1.tgz'));
print "\n2.tgz";
r(new PharData('2.tgz'));
print "\norig dir:";
chdir('orig-dir');
r(new RecursiveDirectoryIterator('./'));
Here's the fixture:
mkdir -p orig-dir/subdir; touch orig-dir/{a,b,subdir/c}; cd orig-dir
tar czf ../1.tgz *
tar czf ../2.tgz ./
cd ../
# put the test code file here and run with php test-code.php
Here's the output:
1.tgz has 4 files:
phar:///tmp/t/1.tgz/a
phar:///tmp/t/1.tgz/b
phar:///tmp/t/1.tgz/subdir/c
2.tgz has 5 files:
orig dir: has 1 files:
./b
./.
./subdir/.
./subdir/c
./subdir/..
./..
./a
Q. Why is phar having such difficulties with the 2nd tar file? (I'm on php 5.6)

PHP shell execution create dynamic command

Following Command search a file in a directory and zip it,it works well
$command = "cd {$root}/files && mkdir -p {$identifier} && zip -jFS -0 {$root}{$zipname} 2491/'test&.txt'";
exec($command);
But changing files as variable is not allowing shell to execute,the below code does not work
$container_name = "2491";
$files = Array ( '0' => 'test&.txt' ,'1' => 'test5.txt','2' => 'test6.txt');
$files = " " . $container_name . "/'" . implode("' " . $container_name . "/'", $files) . "'";
$files = str_replace('$', '\$', $files);
$command = "cd {$root}/files && mkdir -p {$identifier} && zip -jFS -0 {$root}{$zipname} {$files}";
exec($command);
$root,$identifier,$zipname not causing the problem,its $files What can be the issue?
Update
var_dump for $command before execution:
string(128) "cd /var/www/files && mkdir -p zip--1 && zip -jFS -0 /var/www/files/zip--1/1002_22-06022-06022-_content.zip 2491/'test&.txt'"
which if I execute as
exec("cd /var/www/files && mkdir -p zip--1 && zip -jFS -0 /var/www/files/zip--1/1002_22-06022-06022-_content.zip 2491/'test&.txt'");
runs perfectly
Error Reponse:
zip error: Nothing to do! (/var/www/files/zip--1/1002_22-06022-06022-_content.zip)
I got it fix, issue was with file name having '&' which was chanding to '&', thus breaking the command. To get it I passed through the file name with [htmlspecialchars_decode].1

Categories