ls output changing when used through exec() - php

I'm using the ls command via PHP and exec() and I get a different output than when I run the same command via the shell. When running ls through PHP the year and month of the date get changed into the month name:
Running the command through the shell:
$ ls -lh /path/to/file
-rw-r--r-- 1 sysadmin sysadmin 36M 2011-05-18 13:25 file
Running the command via PHP:
<?php
exec("ls -lh /path/to/file", $output);
print_r($output);
/*
Array
(
[0] => -rw-r--r-- 1 sysadmin sysadmin 36M May 18 13:25 file
)
*/
Please note that:
-the issue doesn't occur when I run the PHP script via the cli (it only occurs when run through apache)
-I checked the source code of the page to make sure that what I was seeing was what I was getting (and I do get the month name instead of the proper date)
-I also run the ls command through the shell as the www-data user to see if ls was giving different output depending on the user (the output is the always the same from the shell, that is I get the date in yyyy-mm-dd instead of the month name)
Update with answer
alias was giving me this:
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
From those aliases I was unable to find a switch that was directly responsible for the time display:
-C list entries by columns
-F append indicator (one of */=>#|) to entries
-A do not list implied . and ..
-a do not ignore entries starting with .
-l use a long listing format
However using --time-style=long-iso in PHP did fix the issue.

ls has a couple command line options for date display format. check that your command line version isn't aliased to include something like ls --time-style=locale. The PHP exec'd version will most likely not have this aliasing present and is using default ls settings.

ls output depends from current locale settings. When you run it from console on behalf yourself it uses your locale settings, but user www-data has own locale settings (which probably differ from your). So, I suggest to you specify locale settings explicitly:
exec("LC_TIME=POSIX ls -lh /", $output);
where instead of POSIX you may substitute locale which you want to use.

Related

Why is PATH on mac not working? [duplicate]

Can anyone explain how python 2.6 could be getting run by default on my machine? It looks like python points to 2.7, so it seems like which isn't giving me correct information.
~> python --version
Python 2.6.5
~> which python
/opt/local/bin/python
~> /opt/local/bin/python --version
Python 2.7.2
~> ls -l /opt/local/bin/python
lrwxr-xr-x 1 root admin 24 12 Oct 16:02 /opt/local/bin/python -> /opt/local/bin/python2.7
When I generate an error, I see what's really getting run. Why could this be?
~> python -error-making-argument
Unknown option: -e
usage: /Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python [option] ... [-c cmd | -m mod | file | -] [arg] ...
Try `python -h' for more information.
And how can I correct it?
From suggestions in comments:
~> alias
alias cp='cp -i'
alias gcc='gcc -Wall'
~> type python
python is /opt/local/bin/python
Bash uses an internal hash table to optimize $PATH lookups. When you install a new program with the same name as an existing program (python in this case) earlier in your $PATH, Bash doesn't know about it and continues to use the old one. The which executable does a full $PATH search and prints out the intended result.
To fix this, run the command hash -d python. This will delete python from Bash's hash table and force it to do a full $PATH search the next time you invoke it. Alternatively, you can also run hash -r to clear out the hash table entirely.
The type builtin will tell you how a given command will be interpreted. If it says that a command is hashed, that means that Bash is going to skip the $PATH search for the executable.
I just checked my .bash_profile, and it contained the following:
# Setting PATH for MacPython 2.6
# The orginal version is saved in .bash_profile.pysave
PATH="/Library/Frameworks/Python.framework/Versions/2.6/bin:/usr/local/git/bin:${PATH}"
export PATH
Commenting this out has fixed my problem.
If someone can tell me why which and type still gave incorrect answers, I'd be very grateful, and will give them a check-mark!
Thanks for all your guidance!

Run PHP shell_exec() like root user

I building one PHP application where I create command line functionality for Linux debian Jessie. All works fne but I need to be able use some commands like root user.
Is there a way to use shell_exec() or similar command to access like root user via PHP?
Idea of this command line is to people who have access to that server can handle with it over internet from any place or device.
Here is image of console:
Executing commands as root via PHP will leave yourself wide open to all sorts of malicious hackery.
Have a look at the "sudo" documentation.
You should be able to set up all the commands you need as "sudo"able scripts. It is much better to write specific scripts with limited functions than to expose the underlying priviledged command.
As in:
exec ('sudo getCurrentUser.sh')
First, you need to add the user that PHP is using to run (most of the time it is www-data) to the sudo group if it is not already assigned.
Then, in your php file:
use sudo -S, so you can pass the password via echo
$exec = "echo your_passwd | /usr/bin/sudo -S your command";
exec($exec,$out,$rcode);
if you have trouble with the paths - use
"bash -lc 'echo your_passwd | /usr/bin/sudo -S your command'"
so you get a new bash that acts like a login shell and has the paths set
Edit your sudoers file
sudo vi /etc/sudoers
Put this line
www-data ALL=(ALL) NOPASSWD: ALL
www-data is the php default user in linux ( replace if necessary )
Use
$output = shell_exec('sudo XXXX');

rsync in bash not parsing php-generated --exclude-from file

My rsync bash script isn't parsing my --exclude-from file that's generated via php, but it will if I manually create (as root) the same exact file locally. I've got a web interface on a Xubuntu 12.10 system that writes rsync --exclude-from files locally and then pushes them via rcp to our (CentOS 6) backup boxes that run the rsync script. (Please spare finger wagging about rcp... I know--don't have a choice in this case.)
Webpage writes file:
PHP:
file_put_contents($exclfile, $write_ex_val);
then pushes to the backup box from a local bash script on the webserver with:
Bash:
rcp -p /path/to/file/${servername}_${backupsource}.excl ${server}:/destination/path
I've compared the permissions and ownership of the hand-created file (that works) with the same file that's php/rcp'd (that doesn't), and they're both the same:
Bash:
stat -c '%a' server_backupsource_byhand.excl
644
stat -c '%a' server_backupsource_byphp.excl
644
ls -l server_backupsource_byhand.excl
-rw-r--r-- 1 root root 6 May 11 05:57 server_backupsource_byhand.excl
ls -l server_backupsource_byphp.excl
-rw-r--r-- 1 root root 6 May 11 05:58 server_backupsource_byphp.excl
In case it's relevant, here's my rsync line:
BASH:
rsync -vpaz -v --exclude-from=${exclfile} /mnt/${smbdir} /backup
I suspect php might be writing the file in a different format (e.g. UTF8 instead of ANSI), but I can't figure out how to test this, and have limited knowledge here.
Does anyone have any suggestions on how to get the php/rcp generated file to parse?
Using diff and file I found out that the php-written version wasn't writing the newline. In my variable definition I was using a "." as "$write_ex_val ." Removing this "." let php write the new lines. I also removed the space between the variable and "\n", although I'm not sure if this contributed to the solution. I'd upvote the comment, Earl, but I don't think I have enough rep. Thanks again.

php cli on linux not working

PHP CLI has suddently stopped working on the server. When running any php file even php -v to get php version I get following error.
Thanks
# php -v
Unknown option: v
php [-f from_encoding] [-t to_encoding] [-s string] [files...]
php -l
php -r encoding_alias
-l,--list
lists all available encodings
-r,--resolve encoding_alias
resolve encoding to its (Encode) canonical name
-f,--from from_encoding
when omitted, the current locale will be used
-t,--to to_encoding
when omitted, the current locale will be used
-s,--string string
"string" will be the input instead of STDIN or files
The following are mainly of interest to Encode hackers:
-D,--debug show debug information
-C N | -c | -p check the validity of the input
-S,--scheme scheme use the scheme for conversion
Type which php on your shell to find which php executable your shell picks from your search PATH.
Use ls -l $(which php) to see if it's a symlink to some other executable.
What you see when running php -v is actually output of the piconv command.
Most possibly, there is a symlink named php pointing to piconv somewhere in your search PATH.
Type echo $PATH to see the order of directories in which your shell searches for an executable php.
EDIT:
Changed whereis to which in the command above.

ls -ltr using PHP exec()

as the problem states..
when i do
exec("ls -ltr > output.txt 2>&1",$result,$status);
its different from the normal output. An extra column gets added. something like
-rw-r--r-- 1 apache apache 211 Jul 1 15:52 withoutsudo.txt
-rw-r--r-- 1 apache apache 0 Jul 1 15:53 withsudo.txt
where as when executed from the command prompt its like
-rw-r--r-- 1 apache apache 211 2010-07-01 15:52 withoutsudo.txt
-rw-r--r-- 1 apache apache 274 2010-07-01 15:53 withsudo.txt
-rw-r--r-- 1 apache apache 346 2010-07-01 15:55 sudominusu.txt
-rw-r--r-- 1 apache apache 414 2010-07-01 15:58 sudominusu.txt
See the difference. So in the first output , my usual awk '{print $8}' fails.
I was facing the same problem with cron. But solved it by calling
./$HOME/.bashrc
in the script. But not happening using php. If somehow i can "tell" php to "exec" from the usual environment. Any help would be appreciated.
In your login shell, ls is probably aliased so that it prints another date. This would be in your .basrc or .bash_profile.
Explicitly pass the --time-style= option to ls to ensure that it prints the date in the expected format when using PHP.
I guess you are only interested in the file names and you want to sort with reverse time.
Try this:
ls -tr1 > output.txt 2>&1
You'll get a list with only the file names, so you don't need awk at all.
Another solution is to specify the time format with "--time-style iso". Have a look at the man page
That's not an extra output, that's a difference in formatting the date. Apparently you have a different locale set in PHP and in bash ("command prompt").
(in bash, running export LANG=C or export LANG=en_US gives the result with three-letter month name)
The output of ls is heavily dependent on the environment (e.g., LANG being the important variable here). Why not use a combination of scandir, stat, and krsort?
function ls($dir_name) {
$finfo = array();
foreach (scandir($dir_name) as $file_name) {
$s = stat(join('/', array($dir_name,$file_name)));
$finfo[$file_name] = $s['mtime'];
}
krsort($finfo);
return array_keys($finfo);
}
This will be safer and a lot more efficient than shelling out to ls. Not to mention that you get the benefit of being about to customize the sorting and filter the results in ways that are difficult to do inside of an exec.
BTW: I am by no means a PHP expert, so the above snippet is likely to be incredibly unsafe and full of errors.

Categories