php cli on linux not working - php

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.

Related

Why piping output of docker-compose exec to grep, breaks it?

I'm running this command to run Drush which is basically a PHP CLI for Drupal, in the running container:
docker-compose -f ../docker-compose.test.yml exec php scripts/bin/vendor/drush.phar -r public_html status-report
The output if this command is fine, it's the list of status information about a specific Drupal instance in the container. I won't be pasting it here as it's long, and irrelevant.
Now let's filter this information by piping it into grep:
docker-compose -f ../docker-compose.test.yml exec php scripts/bin/vendor/drush.phar -r public_html status-report | grep -e Warning -e Error
The result is:
Cro Error L
Gra Warning P
HTT Error F
HTT Warning T
Dru Warning N
XML Error L
Which is wrong, it looks like it has been cut to pieces, and most of it is missing.
Now, if we will disable allocating of pseudo-tty by adding -T flag:
docker-compose -f ../docker-compose.test.yml exec -T php scripts/bin/vendor/drush.phar -r public_html status-report | grep -e Warning -e Error
The output is correct:
Cron maintenance Error Last run 3 weeks 1 day ago
Gravatar Warning Potential issues
HTTP request status Error Fails
HTTPRL - Non Warning This server does not handle hanging
Drupal core update Warning No update data available
XML sitemap Error Last attempted generation on Tue, 04/18/2017
Why is that?
Bonus question, which probably will be answered by the answer to the previous one: Are there any important side effects of using -T?
Docker version 18.06.1-ce, build e68fc7a215
docker-compose version 1.22.0
UPDATE #1:
To simplify things I saved the correct output of the whole scripts/bin/vendor/drush.phar -r public_html status-report into a file test.txt and tried:
docker-compose -f ../docker-compose.test.yml exec php cat test.txt | grep -e Warning -e Error
Interestingly the output is correct now with and witout -T, so it has to have something to do with Drush/php, although I'm still interested what can be a cause of this.
PHP 7.1.12 (cli) (built: Dec 1 2017 04:07:00) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
with Zend OPcache v7.1.12, Copyright (c) 1999-2017, by Zend Technologies
with Xdebug v2.5.5, Copyright (c) 2002-2017, by Derick Rethans
Drush 8.1.17
UPDATE #2:
To isolate problem further I put all content in a PHP file, that is simply printing it, and after:
docker-compose -f ../docker-compose.test.yml exec php php php.php | grep -e Warning -e Error
I'm getting a correct output!
So it has to have something to do with how Drush is printing its messages, but I fail to see what it can be. That could be pretty interesting if we could figure this out.
UPDATE #3:
Ok guys, that's actual magic. The problem happens also with running drush without any commands, to list all available ones. The list of commands is broken when output is being piped, so this can be tested without actual Drupal instance.
Now I want to present you magic.
In drush, output for list of available commands in being generated in commands/core/help.drush.phpin function drush_core_help(). There is this call: drush_help_listing_print($command_categories); I looked into it. Inside is a call drush_print_table($rows, FALSE, array('name' => 20)); that is responsible for generating part of the output that's getting broken.
So inside of it, I decided to intercept the output, just before the last call to drush_print(), by adding simple file_put_contents('/var/www/html/data.txt', $output);
And now it's time for the absolutely magical part for me.
When I execute:
docker-compose -f ../docker-compose.test.yml exec php scripts/bin/vendor/drush/drush -r public_html
The last group of commands can be checked in this file, and in my case it's:
adminrole-update Update the administrator role permissions.
elysia-cron Run all cron tasks in all active modules for specified site using elysia cron system. This replaces the standard "core-cron" drush handler.
generate-redirects Create redirects.
libraries-download Download library files of registered libraries.
(ldl, lib-download)
libraries-list (lls, Show a list of registered libraries.
lib-list)
BUT, if I execute the same command, but the output will be piped or redirected, so for example:
docker-compose -f ../docker-compose.test.yml exec php scripts/bin/vendor/drush/drush -r public_html | cat
SOMETHING DIFFERENT WILL BE SAVED INTO A FILE:
adminrole-update U
p
d
a
t
e
t
h
e
a
d
m
i
n
i
s
t
r
a
t
o
r
r
(and the rest of the broken output)
So the fact of piping/redirecting of the output, influences execution of the command, before the pipe/redirection actually happens.
How is that even possible? O_o
It's not uncommon for a command-line program to change its output presentation based on whether its output is a terminal, or not. For example, ls by itself, with no options, displays files in a columnar format. When piped, the output changes to a list of one-file-per-line. You can see this in the source code for GNU ls:
case LS_LS:
/* This is for the 'ls' program. */
if (isatty (STDOUT_FILENO))
{
format = many_per_line;
set_quoting_style (NULL, shell_escape_quoting_style);
/* See description of qmark_funny_chars, above. */
qmark_funny_chars = true;
}
else
{
format = one_per_line;
qmark_funny_chars = false;
}
break;
You can emulate the behavior of ls | ... with the explicit argument ls -1, and this too is not uncommon: programs that implicitly change their output presentation often provide a way to explicitly engage that alternate presentation.
Support for this isn't just a convention: it's actually a requirement for ls in POSIX:
The default format shall be to list one entry per line to standard output; the exceptions are to terminals or when one of the -C, -m, or -x options is specified. If the output is to a terminal, the format is implementation-defined.
This all may seem magical: how does ls know it's got a pipe following it since it comes before the pipe? The answer is quite simple, really: the shell parses the whole command line, sets up the pipes, and then forks the respective programs with the input/output wired to pipes appropriately.
So, what part of the command is doing the alternate presentation? I suspect it's an interaction between the environment of your exec and the column width calculation in drush. On my local environment, drush help | ... doesn't produce any unusual results. You might try piping to (or through) cat -vet to discover any unusual characters in the output.
That said, regarding docker-compose specifically: based on this thread, you're not the only one who has encountered this or a similar issue. I've not trawled the docker source code, but - generally - not allocating a pseudo-tty will make the other end act like a non-interactive shell, which means things like your .bash_profile won't run and you won't be able to read stdin in the run command. This can give the appearance of things not working.
The thread linked above mentions a work around of this form:
docker exec -i $(docker-compose ...) < input-file
which seems reasonable given the meaning of -i, but it also seems rather convoluted for basic scripting.
The fact that -T makes it work for you suggests to me that you have something in your .bash_profile (or similar login-shell-specific start up file) that's changing certain values (maybe COLUMNS) or altering the values in such a way as to have the observed deleterious effect. You might try removing everything from those files, then adding them back to see if any particular one causes the issue.
I didn't read that very detailed question, but from glancing over it, I'd say the -T option to the exec subcommand is essential if you want to process stdout and stderr in the environment where you execute docker-compose.

PHP exec() works in command line but not in web

I'm trying to use jarun's "googler" in a PHP script in order to search YouTube and find the URL of the first result. The command I'm executing is googler --np --json -C -n 1 -w youtube.com -x <name of youtube video>, and it works perfectly on my local machine. Here is my code:
<?php
exec("googler --np --json -C -n 1 -w youtube.com -x thomas the dank engine", $results);
var_dump($results);
?>
When I execute this in the command line, it works perfectly as it should, but when I do it via a web browser or a GET request, it does not work. I am aware that it is being executed as another user. In my case, it's the user www-data, so I gave that user full sudo permissions without a password, and did the following commands:
sudo -u pi googler --np --json -C -n 1 -w youtube.com -x thomas the dank engine
as well as
su - pi -c 'googler --np --json -C -n 1 -w youtube.com -x thomas the dank engine'
neither of these worked. Does it have to do with googler? What am I doing wrong?
When adding 2>&1 to the command, I get the following error message:
stdout encoding 'ascii' detected. googler requires utf-8 to work properly. The wrong encoding may be due to a non-UTF-8 locale or an improper PYTHONIOENCODING. (For the record, your locale language is and locale encoding is ; your PYTHONIOENCODING is not set.) Please set a UTF-8 locale (e.g., en_US.UTF-8) or set PYTHONIOENCODING to utf-8.
Try putting:
putenv("PYTHONIOENCODING=utf-8");
in the script before calling exec(). googler apparently requires the locale or this environment variable to be set.
You must remove exec from the disable_functions parameter in the php.ini file for your server module installation of PHP (which is separate from your CLI installation). It is typically disabled by default for the server module.

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!

Setting environment variables with the built-in PHP web server

PHP 5.4 supports a built-in web server for development purposes. The app we are developing is configured via environment variables.
With Apache you'd do this:
SetEnv FAVORITE_COLOR white
With the normal CLI you can do this:
$ export FAVORITE_COLOR=black
$ php -a
php > echo $_SERVER['FAVORITE_COLOR'];
Is there a way to set these variables for the built-in web server?
Looks like E is excluded from variable_order setting running the built-in server. If you add the E to the variable_order setting, it works:
test.php
<?php
var_dump($_ENV['FOO']);
shell:
FOO=BAR php -d variables_order=EGPCS -S localhost:9090 /tmp/test.php
output:
string 'BAR' (length=3)
Tested on PHP 5.4.12
I use Window DOS to start the PHP server. I store my server startup commands in a text batch file (.bat) to save me from having to select and copy all of the commands at once and paste it into the DOS terminal (note the last blank line that I copy as well so the PHP server will automatically start when I paste the commands into DOS, otherwise I would need to manually use the Enter key to start the server).
Q:
cd Q:\GitLabRepos\myapps\test1
set APPLICATION_TITLE=My testing application with this first env variable
set SOME_OTHER_ENV_VAR2={"myJsonElement":"some value"}
E:\PHP8\php.exe -d variables_order=E -S localhost:8000 -c php.ini
The commands above explained:
The first line Q: changes to the drive where my code resides. The second line cd Q:\GitLabRepos\myapps\test1 changes directories to my root PHP application code (which is where I want to start the PHP server). Next I set some environment variables on lines 3 and 4. Then finally I start the PHP server with the -d variables_order=E parameter so I can use either $_ENV or getenv() to retrieve the environment variable values in my PHP code (eg. $_ENV['APPLICATION_TITLE'] or getenv('APPLICATION_TITLE')). If you exclude -d variables_order=E from the server startup command then you can only use getenv() to access the environment variables. I use the -c php.ini parameter to load additional PHP settings from a php.ini file but this can be excluded for simple server setup.
Then if I have a Q:\GitLabRepos\myapps\test1\index.php script with the following code:
<?php
echo getenv('APPLICATION_TITLE').'---'.$_ENV['APPLICATION_TITLE'].'...'.getenv('SOME_OTHER_ENV_VAR2');
?>
If I visit localhost:8000 in a web browser I should see
My testing application with this first env variable---My testing application with this first env variable...{"myJsonElement":"some value"}.
On Windows:
SET FOO=BAR
php -s localhost:9090

ls output changing when used through exec()

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.

Categories