In Windows 7, running php.exe from C:\wamp64\bin\php\php5.6.25\php.exe,
I find that the following prints the PHP usage instructions.
echo 4;|php -r <-- prints php usage instructions
C:\wamp64\bin\php\php5.6.25>echo 4;|php -r
Usage: php [options] [-f] <file> [--] [args...]
php [options] -r <code> [--] [args...]
However, a friend claims that the same command echo 4;|php -r (or perhaps he means echo '4;'|php -r works for him using Linux.
How can I get this behaviour in windows?
Note I'm aware of php -r used to run some code passed as a parameter following it, i'm asking about it running a file or accepting stdin.
There's a few points of confusion here, so I'll do my best to itemize what's wrong.
First, the original command can't work on Linux/POSIX shell because it's not valid:
echo 4; | php -r
Where ; has significant meaning, it's a command separator, and a command can't begin with |.
Fixing this, you get:
echo '4;' | php -r
Where that is at least valid as far as the shell is concerned, but it's still not enough for PHP to deal with. The -r argument requires a second term, code, which is the code to be evaluated. This needs to be supplied inline, not externally as you usually would.
Specifically the -r flag does not mean "run the input file as if it has <?php ... ?> surrounding it" but instead it means "run this bit of code in PHP mode".
For example:
echo '4;' | php
Technically works, but it's not evaluated as PHP code, so it's pointless.
The version that does work in POSIX shell is this:
php -r `echo '4;'`
Where that inlines the output of echo '4;' into the command-line argument itself. I'm not sure Windows can do that without PowerShell involved.
The -r flag is intended for quick little snippets like:
php -r 'echo 5 * 9;'
Where that prints 45 as expected.
Try
echo 4 | php -r
instead of terminating echo 4 and piping nothing into php.
Not that it should matter, "-r" means nothing to php. Nor does 4 (apart from rhyming).
Related
I have a small script I tested on the command line using php test.php.
test.php
<?php
exec('ps -acux | grep test', $testvar);
print_r($testvar);
?>
This works fine. I am able to run the script and get the desired result. However, when I add the code to a file being run by my PHP server, the result is empty.
My OS is FreeBSD. Looking at the man page for ps the only restriction I see is on the -a option. It states:
If the security.bsd.see_other_uids sysctl is set to zero, this option
is honored only if the UID of the user is 0.
My security.bsd.see_other_uids is set to 1.
$ sysctl security.bsd.see_other_uids
security.bsd.see_other_uids: 1
The only thing I can think of is that the command is being run by my user when I run it via the command line whereas when run by PHP, it's being run by www. I'm not seeing anything in the manual of ps that indicates www shouldn't be able to run the command.
As per the comments you need to redirect stderr to stdout. This is achieved by 2>&1 to the end of your command. So an example of the PHP exec() is as follows:
exec('ps -acux | grep test 2>&1', $testvar);
This allows you to see potential errors. In my case there was no error and likely a bug of some sorts. However this is useful in all cases where you execute a command. If any error were to occur you can retrieve it to see what is happening with your command.
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!
I was reading about specifics of PHP in CLI mode and I can't explain for myself what utility has -f flag.
It's possible execute any php script as "php name_of_script.php" or "php -f name_of_script.php"
I guess this option is just kind of syntactic sugar. Also its existence can be perhaps explained by the fact that it's more obvious for user when he sees -f that file is executed. I can't make up any other explanations. Do someone see any other usage of it?
PHP has a very long history with a lot of the design decisions lost in the mists of time; I'm not sure anyone will be able to tell you for certain why there's both a -f option and the ability to run a file without any options at all.
However, it certainly seems designed for user convenience; most command line users would expect an interpreter to interpret a filename provided as a single parameter, and it's the most common use-case, so making it the quickest to type makes sense. My guess would be that the PHP CLI started off with just the -f option, and the option to run a file by providing just the filename was added later to make people's lives easier. The -f was retained for backwards compatibility.
I can think of one case where the -f option is useful: if the filename starts with a hyphen, for example -.php.
When provided as a single parameter, this will be treated as an option, and fail:
$ php -.php
Usage: php [options] [-f] <file> [--] [args...]
php [options] -r <code> [--] [args...]
php [options] [-B <begin_code>] -R <code
...
However, with -f, it'll work:
$ php -f -.php
<script executes successfully>
It's quite simple, and I'm out of ideas. I'm sure there is a quick workaround.
exec('echo 123 &> /var/log/123.log');
I'm sure it's not about the permissions, because the file 123.log is created, but it's just- empty. I've also tried shell_exec, but it doesn't create the file at all.
Also tried all variants of redirection, i.e. 1> 2> >.
Using PHP to capture the output is not the option, as the output in production is huge, and I don't want to run into memory issues.
Any ideas appreciated.
Btw, I'm using Ubuntu 12.04 LAMP.
Debian and Debian based Linux distributions like Ubuntu are using dash and not bash as /bin/sh by now.
&> is a bash extension, the dash does not know about.
The correct posix-compatible way to write cmd &> file is cmd > file 2>&1
cmd > file 2>&1 works in all posix-compatible shells: dash, bash, ksh, zsh, ash ...
So you need to change your code to:
exec('echo 123 > /var/log/123.log 2>&1');
Try shell_exec without &:
echo shell_exec("echo 123 > /var/log/123.log");
Only thing that did help was to create a shell script with exec permissions, e.g. test.sh:
#!/bin/bash
echo 123 &>> /var/log/123.log
and execute it like this:
shell_exec('[full path to]/test.sh');
So, redirection operator is not important, but everything else is (#! directive, shell_exec).
I'm working on interfacing a microcontroller with a lamp server. I am trying to run the command echo -e -n "data \r" > /dev/ttyUSB0 using shell_exec in php but with no results. It works just fine from the command line. Doing a little experimenting, I discovered that echo -e -n "1 \r" actually echoes -e -n 1. Is there a reason it won't take the -e or -n options?
Here's my code:
<?php
shell_exec('echo -e -n "1 \r" > /dev/ttyUSB0');
?>
Instead of using shell_exec and echo, why not use PHP's filesystem functions?
file_put_contents('/dev/ttyUSB0', "1 \r");
There are some other functions too, try this function maybe you get your answer.
exec(command, $output);
This function takes a command and assigns to $output an array where each element is a line of the generated output.
I ran into similar problem, calling from php
php > echo shell_exec("echo -e aaa\tbbb");
-e aaa bbb
note, that output contains "-e", while I have expected that 'echo' command will interpret -e as flag and would not send it to output.
After doing some investigation I came to following conclusion:
when exec or shell_exec are called from php - new shell interpreter is launched.
php launches "sh".
When I was running on CentOS sh was a symlink to bash, and exec("echo ...") worked as I would have expected.
Now I am running Ubuntu. sh is a symlink to dash, not bash!
And final root cause - builtin echo command in dash does not have/understand '-e' flag, so it just forwards it to output
This is an old question but it goes what worked for me in case someone else comes across with this as well.
Yesterday night I've messing around and struggling with this myself. For this to work, the command you need to use should start by calling the echo bin directly /bin/echo... instead of only echo.
Also don't forget to use single quote /bin/echo... instead of double quote to avoid PHP null byte detection error (this part you did correctly).
I had a similar problem running with -e, I was trying to change the password from a php
running this didnt work
exec("echo -e \"$pass\\n$pass\" | passwd $user");
It said passwords dont match. Checking the echo i saw that -e was includes as a part of the echoing so i changed it to
exec("echo \"$pass\\n$pass\" | passwd $user");
And then it worked.