pass php variables in a bash script - php

I want to run this script bash
#!/bin/bash
# file name: myscript.sh
PROJECT_DIR=$1
mkdir $PROJECT_DIR
mkdir $PROJECT_DIR/PolySkills
mkdir $PROJECT_DIR/PolySkills/cr
mkdir $PROJECT_DIR/PolySkills/cr/corrections
mkdir $PROJECT_DIR/PolySkills/cr/corrections/jpg
mkdir $PROJECT_DIR/PolySkills/cr/corrections/pdf
mkdir $PROJECT_DIR/PolySkills/cr/diagnostic
mkdir $PROJECT_DIR/PolySkills/cr/zooms
mkdir $PROJECT_DIR/PolySkills/data
mkdir $PROJECT_DIR/PolySkills/exports
mkdir $PROJECT_DIR/PolySkills/scans
mkdir $PROJECT_DIR/PolySkills/copies
cd $PROJECT_DIR/PolySkills
cp ~/file.tex $PROJECT_DIR/PolySkills
For the variable "PROJECT_DIR" that represents a path in which I will create folders, I want to retrieve its value from a php variable.
I looked at some examples on the internet and I tried one but it does not work. This is what i used :
chdir('~/');
$pathtofile = "~/ExportEval/".$NomUE."/".$NomOcc."/".$Numtudiant;
$directory=$pathtofile."/AMC_Project";
$output = exec("./myscript $directory");
Knowing that the script file "myscript " exists in home "~ /"
thank you for your help :)
I update my question :
I found what is the problem but I don't see what the solution as the variable $NomUE is composed of a sentence separated by spaces it considers that $ 1 is only the first of this sentence if I change $ 1 by $ 2 it takes the second word of that same sentence! I don't understand why it does not take $pathtofile as path !

You need to always escape variables before sending them to the command line. Also, ~ has no meaning here and there's no reason to use chdir(). Just use a fully qualified pathname instead:
<?php
$pathtofile = "/home/someuser/ExportEval/$NomUE/$NomOcc/$Numtudiant";
$directory = escapeshellarg("$pathtofile/AMC_Project");
$output = exec("/home/someuser/myscript $directory");
You may have problems running a script in a home directory, and reading from that directory. Best is to put the script in a proper location such as /usr/local/bin/.

Related

Use php to execute a command in terminal

Hello Im trying to create a php that executes a command in terminal. I dont know why but my code does not work.
When I go to ..../api.php?link=hello
it does not create the folder with that name
<?php
$parameter = $_GET['link'];
$output = shell_exec('sudo mkdir $parameter');
echo "<pre>$output</pre>";
?>
Fixed my command was not running because I had to put "sudo mkdir $parameter" not 'sudo mkdir $parameter' because my $parameter had symbols that confused the command. Thanks everyone for helping me figuring this out!
According to the documentation of shell_execute (https://www.php.net/manual/en/function.shell-exec.php), You need to disabel safe mode.
On linux servers
Run the following command:
`vi /etc/php.ini`
Go to the line safe_mode = on and press the "i" key.
Change the line to safe_mode = off and press the "Esc" key.
Type :wq! to save your file.
On Windows Servers
Open c:\windowsphp.ini in Notepad.
Change the line safe_mode = on to safe_mode = off.
Save and close php.ini.
Generally speaking , to problem is due to the permission , so here is the solution :
Let's suppose your file php that contain the exec command exist inside a folder nammed src
src/api.php
The src folder should have as owner www-data:www-data instead of something else to make php able to exec command .
$output = shell_exec('sudo mkdir $parameter 2>&1');
Add 2>&1 to see the error occuring inside .
When modifying the permission , you can exec the command, but be ware
that the file or folder yu are creating should be inside the src
folder , if it's another place , the parent folder should have as
owner www-data:www-data

how to show files in current directory with embedded php webserver (as command line)

I want to run the simple embedded webserver from php via command line
php -S 0.0.0.0:8000
and let it show the content of the current directory.
As of the man page the only possible additional option to -S is -t for the document root. I know I can just create a index.php file with the following content
<html>
<body>
<?php
$directory = "./";
$files = glob($directory . "*");
foreach($files as $file) {
echo "".basename($file)."<br>";
}
?>
</body>
</html>
but I don’t want to create a file in that directory.
Isn’t it possible to run that code as a command line argument? I have tried it with the option -r and even with a virtual bash file and the -F-option as follows: -F <(… php code here …) but it seems true that the -S command only accepts -t as additional command.
Is there any trick to achieve it?
PS: I know that with python 2 or python 3 it is easily possible to show the current directory with python’s embedded webserver with
python -m SimpleHTTPServer # python 2
python -m http.server # python 3
but I want to do it with php.
Replace "./" from the assignment of variable $directory with the complete path of the directory you want to serve. Or, even better, change it to:
$directory = $_SERVER['DOCUMENT_ROOT'].'/';
to serve the path you provide as argument to -t in the command line.
Put index.php wherever you want in the file system and add its location (with complete path) to the end of the php command line.
If, for example, you save it as /home/erik/index.php, start PHP as:
php -S 0.0.0.0:8000 -t /home/erik/web /home/erik/index.php
PHP will use the script as a router. It will run it on every request and you can change it to interpret the request ($_GET[], $_SERVER[]) and generate different output, depending of the requested path and query string.

How to fix PHP (shell_)exec() permissions for copy pasting?

The following command executed in PHP's shell_exec() function:
echo 'A' ; cp -v $original $destination ; echo 'B' ; whoami
Will output ABapache, but nothing else. The copy command does not seem to be working. ($original and $destination are replaced with the correct path).
I made the apache user the owner of the folders I'm using for the cp command. It still doesn't work, I tried chmodding and more, nothing seems to work.
Is it blocked within PHP to run the cp command?
Thanks!

unix mv --backup=numbered

I'm trying in php to move a folder but keep both files in the dest folder if exist duplicate.
i tried todo that in recursion but its too complicated so many things can go wrong for example file premissions and duplicate files\folders.
im trying to work with system() command and i cant figure out how to move files but keep backup if duplicate without destroying the extension
$last_line = system('mv --backup=t websites/test/ websites/test2/', $retval);
gives the following if file exist in both dirs:
ajax.html~
ajax.html~1
ajax.html~2
what im looking for is:
ajax~.html
ajax~1.html
ajax~2.html
or any other like (1), (2) ... but without ruining the extension of the file.
any ideas? please.
p.s must use the system() command.
For this problem, I get sed to find and swap those extensions after the fact in this function below (passing my target directory as my argument):
swap_file_extension_and_backup_number ()
{
IFS=$'\n'
for y in $(ls $1)
do
mv $1/`echo $y | sed 's/ /\\ /g'` $1/`echo "$y" | sed 's/\(\.[^~]\{3\}\)\(\.~[0-9]\{1,2\}~\)$/\2\1/g'`
done
}
The function assumes that your file extensions will be the normal 3 characters long, and this will find backups up to two digits long i.e. .~99~
Explanation:
This part $1/`echo $y | sed 's/ /\\ /g'` $1/`echo "$y"
represents the first argument (the original file) of mv but protects you from space characters by adding an escape.
The last part $1/`echo "$y" | sed 's/\(\.[^~]\{3\}\)\(\.~[0-9]\{1,2\}~\)$/\2\1/g' is of course the target file where two parenthetic groups are swapped .i.e. /\2\1/
if you want to keep the original files and just create a copy then use cp not mv.
If you want to create a backup archive then do a tar gzip of the folder like this
tar -pczf name_of_your_archive.tar.gz /path/to/directory/to/backup
rsync --ignore-existing --remove-source-files /path/to/source /path/to/dest
Use rsync with the --backup and --backup-dir options. eg:
rsync -a --backup --backup-dir /usr/local/backup/2013/03/20/ /path/to/source /path/to/dest
Every time a file might be overwritten it is copied to the folder given, plus the path to that item. eg: /path/to/dest/path/to/source/file.txt
From the looks of things, there don't seem to be any built in method for you to back up files while keeping the extension at the correct place. Could be wrong, but I was not able to find one that doesn't do what your original question already pointed out.
Since you said that it's complicated to copy the files over using php, perhaps you can do it the same way you are doing it right now, getting the files in the format
ajax.html~
ajax.html~1
ajax.html~2
Then using PHP to parse through the files and rename them to the format you want. This way you won't have to deal with permissions, and duplicate files, which are complications you mentioned. You just have to look for files with this format, and rename them.
I am not responding strictly to your question, but the case I am presenting here is very common and therefore valid!
Here's my hack!
TO USE WITH FILES:
#!/bin/bash
# It will find all the files according to the arguments in
# "<YOUR_ARGUMENT_TO_FIND_FILES>" ("find" command) and move them to the
# "<DEST_FOLDER>" folder. Files with the same name will follow the pattern:
# "same_name.ext", "same_name (1).ext", "same_name (2).ext",
# "same_name (3).ext"...
cd <YOUR_TARGET_FOLDER>
mkdir ./<DEST_FOLDER>
find ./ -iname "<YOUR_ARGUMENT_TO_FIND_FILES>" -type f -print0 | xargs -0 -I "{}" sh -c 'cp --backup=numbered "{}" "./<DEST_FOLDER>/" && rm -f "{}"'
cd ./<DEST_FOLDER>
for f_name in *.~*~; do
f_bak_ext="${f_name##*.}"
f_bak_num="${f_bak_ext//[^0-9]/}"
f_orig_name="${f_name%.*}"
f_only_name="${f_orig_name%.*}"
f_only_ext="${f_orig_name##*.}"
mv "$f_name" "$f_only_name ($f_bak_num).$f_only_ext"
done
cd ..
TO USE WITH FOLDERS:
#!/bin/bash
# It will find all the folders according to the arguments in
# "<YOUR_ARGUMENT_TO_FIND_FOLDERS>" ("find" command) and move them to the
# "<DEST_FOLDER>" folder. Folders with the same name will have their contents
# merged, however files with the same name WILL NOT HAVE DUPLICATES (example:
# "same_name.ext", "same_name (1).ext", "same_name (2).ext",
# "same_name (3).ext"...).
cd <YOUR_TARGET_FOLDER>
find ./ -path "./<DEST_FOLDER>" -prune -o -iname "<YOUR_ARGUMENT_TO_FIND_FOLDERS>" -type d -print0 | xargs -0 -I "{}" sh -c 'rsync -a "{}" "./<DEST_FOLDER>/" && rm -rf "{}"'
This solution might work in this case
cp --backup=simple src dst
Or
cp --backup=numbered src dst
You can also specify a suffix

tar file preserves full path. how to stop it?

I am trying to create a tar archive on my server through PHP as follows:
exec('tar -cvf myfile.tar tmp_folder/innerfolder/');
It works fine, but the saved file preserves the full path including tmp_folder/innerfolder/
I am creating those on the fly for users, so it's a bit unusable for users to have this path while extracting. I have reviewed this topic - How to strip path while archiving with TAR , but in the explanation the guy doesn't give an example, and I don't quite understand what to do.
Please, tell me with an example, how to add files to tar in a way that it does not preserve the 'tmp_folder/innerfolder/' part in archive?
Thanks in advance
Use the -C option to tar:
tar -C tmp_folder/innerfolder -cvf myfile.tar .
you can cheat..
exec('cd /path/to/tmp_folder/ && tar -cvf /path/to/myfile.tar innerfolder/');
This would would give your users just the innerfolder when they extracted the tarball
You can use --transform
tar -cf files.tar --transform='s,/your/path/,,' /your/path/file1 /your/path/file2
tar -tf files.tar
file1
file2
More info: http://www.gnu.org/software/tar/manual/html_section/transform.html
tar czf ~/backup.tgz --directory=/path filetotar
If you want to preserve the current directory name but not the full path to it, try something like this (executed from within the directory that you want to tar; assumes bash/zsh):
ORIGDIR=${PWD##*/}
tar -C `dirname $PWD` -cvf ../archive.tar $ORIGDIR
Here's some detail; first:
ORIGDIR=${PWD##*/}
.. stores the current directory name (i.e. the name of the directory you're in). Then, in the tar command:
-C `dirname $PWD`
.. switches tar's "working directory" from the standard root ("/") to the parent of the folder you want to archive. Strangely the -C switch only affects the path for building the archive, but not the location the archive itself will be stored in. Hence you'll still have to prefix the archive name with "../", or else tar will place it within the folder you started the command in. Finally, $ORIGDIR is relative to the parent directory, and so it and its contents are archived recursively into the tar (but without the path leading to it).

Categories