Cannot run shell command through php exec, but can as user on shell? - linux

I'm trying to get exiftool to work on my dedicated server. The issue is that PHP exec seems to run different than when a command is run as a user. Oddly enough, PHP shows up as the same user I log in with, but it does not behave the same with system commands.
Oddly enough everything works great on my localhost, but not on my server.
So as mentioned, running exiftool commands logged in via ssh is fine.
But running in a php testing script (note I've installed exiftool on each tested directory, and it runs through ssh), nothing is accessible, though it runs as user orangeman...
And it fails
Here is an update - having been on this all day:
On the shell:
-bash-4.1$ which exiftool -a
~/perl5/bin/exiftool
/usr/bin/exiftool
~/perl5/bin/exiftool
In PHP shell_exec('exiftool -a');
/usr/bin/exiftool
And here is what that file links to:
lrwxrwxrwx 1 root root 33 May 15 02:10 exiftool -> /home/orangeman/perl5/bin/exiftool
I've also tried creating symlinks of various sorts, tampering with the main $PATH variable via putenv(); in php ... I'm truly in the dark here. Works on localhost, not on dedicated server.
I've updated this with a bounty - its a serious issue in development.
I'm on a dedicated server, and the problem is as outlined above.
UPDATE
Per #gcb suggestion, I was able to print out the error that is occurring when php's exec() function runs the system command with no effect.
PHP
<?php
exec('exiftool 2>&1', $output, $r);
var_dump($output, $r);
?>
Output:
array(2) {
[0]=>
string(230) "Can't locate Image/ExifTool.pm in #INC (#INC contains: /bin/lib /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /bin/exiftool line 33."
[1]=>
string(59) "BEGIN failed--compilation aborted at /bin/exiftool line 33."
}
UPDATE
#gcb's solution worked. Thank you very much.

So you do not have a php problem now, but a perl one. your include path is bad.
Answer here.
You either have to install the ExifTool libraries in the
standard location (ie. somewhere in the #INC directories
listed in your post), or add the location to the include path,
something like this:
Code:
#!/usr/bin/perl
BEGIN { unshift #INC, "PATH_TO_DIRECTORY_CONTAINING_LIBRARIES" }
use Image::ExifTool;
You should be able to add "Image/ExifTool.pm" to the path you add
to find the ExifTool module.
- Phil
I still think using my suggestion #3 from the previous answer will fix it. If not and you really want to know the reason, create a new perl script that just outputs the contents of #INC and run it via the shell and via php. you will see the difference, then you need to find which login script is not being honored in php and open a bug against php for shell_exec not respecting it...
though the easier solution for your problem (as it does not look like you are too interested in explanations) is to just set the PERLLIB var before calling the script.
So, just do:
find / -name ExifTool.pm This will tell you where the lib is installed. let's say this returns /example/perl/Image/ExifTool.pm
append PERL5LIB=/example/perl/ to your exec() call.
exec("PERL5LIB=/example/perl/ /var/www/myscript/execscript.sh {$param}"); #and

0) you should look on your error log. usually under /var/log/apache/error
it will have messages such as "access denied" or something else.
1) you are clearly not getting enough output of that command to see any error. so try to run it with exiftool 2>&1. this will redirect stderr to stdout, so errors will appear on the output. not sure if that is relevant or php already does that. you may also want to use passthru instead of exec
2) safe-mode exec dir
your file may be out of your safe mode exec dir. read this up:
http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.safe-mode-exec-dir
3) all else fails, run the command as a login shell, which should have the same scripts loaded as when you login in via ssh. just replace exec with shell_exec
...i'm pretty sure looking at the error log will solve your mistery.

One possibility is that on the command line, your $PATH had been set/modified by both your $HOME/.bashrc and your $HOME/.bash_profile because your command line is a log-in shell. When PHP is invoked by the Web server, it runs as "orangeman" BUT only as a shell, not a log-in shell, so its $PATH may not be the same, which is what you're seeing here.
Have you tried putting export PATH="what:you:want:your:PHP:path:to:be" in your $HOME/.bashrc?

I believe this is happening because you have a private installation of perl for you user.
Basically #INC is an array which perl uses for locate its library, and it does not contain the path for your installation library.
There are a couple of ways to change #INC which you can find on the below link:
http://perlmaven.com/how-to-change-inc-to-find-perl-modules-in-non-standard-locations
I hope this helps.

Related

#reboot crontab has no effect

I have this crontab #reboot "/home/pi/Desktop/TV Scraper 2.0/run.sh" set up and for whatever reason it doesn't seem to run the bash file on reboot.
Typing "/home/pi/Desktop/TV Scraper 2.0/run.sh" on the terminal actually runs the script, so I know it's correct.
This is what's inside run.sh just in case:
#!/bin/bash
cd "/home/pi/Desktop/TV Scraper 2.0"
node ./app.js
I've also tried using #reboot root sh "/home/pi/Desktop/TV Scraper 2.0/run.sh" as well, but it doesn't work either.
How can I move forward with this? My knowledge of Linux is very limited. All I need is to have some Node and Python3 scripts run on every reboot. On Windows that's such an easy task: I've tried CRON, rc.local and autostart, nothing works.
My guess is that node is not available via cronjob, since its containing directory is not in your PATH environment variable. When you execute the script manually, it's probably available via PATH.
An easy fix for this is to use the full path, which you can get by executing which node. The result should be something like /usr/bin/node. Then you can use that, instead of just node.
For debugging purpose you can also redirect stdout and stderr to a file, so the last line in your script would look like this:
/usr/bin/node ./app.js &>/tmp/cron-debug.log
If that doesn't fix it, i would rename the directory "TV Scraper 2.0" and replace the whitespace characters with something like an underscore. Directory and file names are less likely to cause problems if you avoid whitespaces.

Find the reason of a file deletion

When I run in the terminal a script which compiles different things by running other scripts, it shows up an error, telling me that the file XXX doesn't exist. But it existed before I ran the script. Thus, I would like to find out what script/program/process deleted the file to fix the bug.
I looked at this but it didn't help me: I am looking for the program at the origin of the deletion, not the user. Additionally, auditctl and iwatch don't exist on the machine I am using.
Please note that I am not interested in what files are deleted (I perfectly know which).
Also, I can recreate XXX to run again the script.
How to simply find out what causes the deletion of XXX?
Two possibilities come to mind how to debug a shell script:
Use strace; the function call you're looking for is most probably unlink(). From the surrounding calls you should be able to deduct the context the deletion is called from.
Switch on command echo with set -x or the shebang #!/bin/bash -x (for Bash) and grep for rm and perhaps unlink. However the deletion may occur in some binary that's called somewhere, in that case you won't find anything this way.
Redirect the output to a file to make searching easier.

Perl script in linux environment is not working via cron

When I try to run a Perl script which is called via Linux script manually it works fine but not executable via CRON.
Linux_scrip.sh conatains Perl_script and the command is,
perl_path/perl Perl_script.pl
I got perl_path using which perl command.
Can anyone suggest why is it not executable via CRON entry.
Most likely suspects:
Current work directory isn't as expected.
Permission issues[1].
Environment variables aren't setup as expected.
Requirement of a terminal can't be met.
See the crontab tag wiki for more pitfalls and some debugging tips.
The first thing you should do is to read the error message.
This isn't likely to be an issue for you own cron job, but I've included it since it's quite a common problem for scripts run from other services.
Most probable cause is current working directory.
Before perl command execution, write a command to change directory.
Something like :
cd perl_path;
perl Perl_script.pl

What's a .sh file?

So I am not experienced in dealing with a plethora of file types, and I haven't been able to find much info on exactly what .sh files are. Here's what I'm trying to do:
I'm trying to download map data sets which are arranged in tiles that can be downloaded individually: http://daymet.ornl.gov/gridded
In order to download a range of tiles at once, they say to download their script, which eventually leads to daymet-nc-retrieval.sh: https://github.com/daymet/scripts/blob/master/Bash/daymet-nc-retrieval.sh
So, what exactly am I supposed to do with this code? The website doesn't provide further instructions, assuming users know what to do with it. I'm guessing you're supposed to paste the code in to some other unmentioned application for a browser (using Chrome or Firefox in this case)? It almost looks like something that could be pasted in to Firefox/Greasemonkey, but not quite. Just by a quick Google on the file type I haven't been able to get heads or tails on it.
I'm sure there's a simple explanation on what to do with these files out there, but it seems to be buried in plenty of posts where people are already assuming you know what to do with these files. Anyone willing to just simply say what needs to be done from square one after getting to the page with the code to actually implementing it? Thanks.
What is a file with extension .sh?
It is a Bourne shell script. They are used in many variations of UNIX-like operating systems. They have no "language" and are interpreted by your shell (interpreter of terminal commands) or if the first line is in the form
#!/path/to/interpreter
they will use that particular interpreter. Your file has the first line:
#!/bin/bash
and that means that it uses Bourne Again Shell, so called bash. It is for all practical purposes a replacement for good old sh.
Depending upon the interpreter you will have different languages in which the file is written.
Keep in mind, that in UNIX world, it is not the extension of the file that determines what the file is (see "How to execute a shell script" below).
If you come from the world of DOS/Windows, you will be familiar with files that have .bat or .cmd extensions (batch files). They are not similar in content, but are akin in design.
How to execute a shell script
Unlike some unsafe operating systems, *nix does not rely exclusively on extensions to determine what to do with a file. Permissions are also used. This means that if you attempt to run the shell script after downloading it, it will be the same as trying to "run" any text file. The ".sh" extension is there only for your convenience to recognize that file.
You will need to make the file executable. Let's assume that you have downloaded your file as file.sh, you can then run in your terminal:
chmod +x file.sh
chmod is a command for changing file's permissions, +x sets execute permissions (in this case for everybody) and finally you have your file name.
You can also do it in your GUI. Most of the time you can right click on the file and select properties; in XUbuntu the permissions options look like this:
If you do not wish to change the permissions, you can also force the shell to run the command. In the terminal you can run:
bash file.sh
The shell should be the same as in the first line of your script.
How safe is it?
You may find it weird that you must perform another task manually in order to execute a file. But this is partially because of a strong need for security.
Basically when you download and run a bash script, it is the same thing as somebody telling you "run all these commands in sequence on your computer, I promise that the results will be good and safe". Ask yourself if you trust the party that has supplied this file, ask yourself if you are sure that you have downloaded the file from the same place as you thought, maybe even have a glance inside to see if something looks out of place (although that requires that you know something about *nix commands and bash programming).
Unfortunately apart from the warning above I cannot give a step-by-step description of what you should do to prevent evil things from happening with your computer; so just keep in mind that any time you get and run an executable file from someone you're actually saying, "Sure, you can use my computer to do something".
If you open your second link in a browser you'll see the source code:
#!/bin/bash
# Script to download individual .nc files from the ORNL
# Daymet server at: http://daymet.ornl.gov
[...]
# For ranges use {start..end}
# for individul vaules, use: 1 2 3 4
for year in {2002..2003}
do
for tile in {1159..1160}
do wget --limit-rate=3m http://daymet.ornl.gov/thredds/fileServer/allcf/${year}/${tile}_${year}/vp.nc -O ${tile}_${year}_vp.nc
# An example using curl instead of wget
#do curl --limit-rate 3M -o ${tile}_${year}_vp.nc http://daymet.ornl.gov/thredds/fileServer/allcf/${year}/${tile}_${year}/vp.nc
done
done
So it's a bash script. Got Linux?
In any case, the script is nothing but a series of HTTP retrievals. Both wget and curl are available for most operating systems and almost all language have HTTP libraries so it's fairly trivial to rewrite in any other technology. There're also some Windows ports of bash itself (git includes one). Last but not least, Windows 10 now has native support for Linux binaries.
sh files are unix (linux) shell executables files, they are the equivalent (but much more powerful) of bat files on windows.
So you need to run it from a linux console, just typing its name the same you do with bat files on windows.
Typically a .sh file is a shell script which you can execute in a terminal. Specifically, the script you mentioned is a bash script, which you can see if you open the file and look in the first line of the file, which is called the shebang or magic line.
I know this is an old question and I probably won't help, but many Linux distributions(e.g., ubuntu) have a "Live cd/usb" function, so if you really need to run this script, you could try booting your computer into Linux. Just burn a .iso to a flash drive (here's how http://goo.gl/U1wLYA), start your computer with the drive plugged in, and press the F key for boot menu. If you choose "...USB...", you will boot into the OS you just put on the drive.
How do I run .sh scripts?
Give execute permission to your script:
chmod +x /path/to/yourscript.sh
And to run your script:
/path/to/yourscript.sh
Since . refers to the current directory: if yourscript.sh is in the current directory, you can simplify this to:
./yourscript.sh
or with GUI
https://askubuntu.com/questions/38661/how-do-i-run-sh-scripts/38666#38666
https://www.cyberciti.biz/faq/run-execute-sh-shell-script/
open the location in terminal then type these commands
1. chmod +x filename.sh
2. ./filename.sh
that's it

shell script not running via crontab, runs fine manually

I have tried exporting my paths and variables and crontab still will not run my script. I'm sure I am doing something wrong.
I have a shell script which runs a jar file. This is not working correctly.
After reading around I have read this is commonly due to incorrect paths due to cron running via its own shell instance and therefore does not have the same preferences setup as my profile does.
Here is what my script looks like today after several modifications:
#!/bin/bash --
. /root/.bash_profile
/usr/bin/java -jar Pharmagistics_auto.jar -o
...
those are the most important pieces of the script, the rest are straightforward shell based.
Can someone tell me what I am doing wrong?
Try specifying the full path to the jar file:
/usr/bin/java -jar /path/to/Pharmagistics_auto.jar -o
I would just tell you what you have already ruled out: Check your path and environment.
Since you have alredy done this, start debugging. Like write checkpoints into a logfile to see how far your script gets (if even started at all), check the cronjob log file for errors, check your mail (cron sends mails on errors) and so on ...
Not very specific, sorry.
"exporting my paths and variables" won't work since crontab runs in a different shell by a different user.
Also, not sure if this is a typo in how you entered the question, but I see:
usr/bin/java
...and I can't help but notice you're not specifying the fully qualified path. It's looking for a directory named "usr" in the current working directory. Oft times for crontab, the cwd is undefined, hence your reference goes nowhere.
Try specifying the full path from root, like so:
/usr/bin/java
Or, if you want to see an example of relative pathing in action, you could also try:
cd /
usr/bin/java
A few thoughts.
Remove the -- after the #!/bin/bash
Make sure to direct script output seen by cron to mail or somewhere else where you can view it (e.g. MAILTO=desiredUser)
Confirm that your script is running and not blocked by a different long-running script (e.g. on the second line, add touch /tmp/MY_SCRIPT_RAN && exit)
Debug the script using set -x and set -v once you know it's actually running
Do you define necessary paths and env vars in your personal .profile (or other script)? Have you tried sourcing that particular file (or is that what you're doing already with /root/.bash_profile?)
Another way of asking this is: are you certain that whatever necessary paths and env vars you expect are actually available?
If nothing else, have you tried echo'ing individual values or just using the "env" command in your script and then reviewing the stdout?
provide full paths to your jar file, and what user are you running the crontab in? If you set it up for a normal user, do you think that user has permission to source the root's profile?

Resources