PHP output piped to ‘less’ is requiring after every command


Piping PHP output to the linux 'less' command causes 'less' to really act up. (CentOS 6.2, didn't happen with CentOS 5.)

When I pipe output from php into 'less', it requires the enter key be pressed after every command, even after the 'j' command (the command to scroll down one line). In addition, the command key is showing up on-screen, and 'less' isn't cleaning up the screen.

So, after running:

$ php -r 'for ($i=0; $i<300; $i++) { print "$i\n";}' | less

and then typing j (which usually scrolls down one line), I see a 'j' character showing up at the bottom of the screen after the ':' character. Pressing enter causes less to finally "take" the j command, and it does indeed scroll, but now I see the ":j" between two adjacent lines of the output:


When using less with the equivalent output from python, everything is fine and less acts normally:

$ python -c 'for i in xrange(1, 300): print i' | less

What's going on and how do I fix it?

More info:

$ less --version
less 436
Copyright (C) 1984-2009 Mark Nudelman

less comes with NO WARRANTY, to the extent permitted by law.
For information about the terms of redistribution,
see the file named README in the less distribution.

$ php --version
PHP 5.3.27 (cli) (built: Aug 26 2013 11:46:37)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2013 Zend Technologies

I'm using on Mac OS X to ssh to the box, then running the php command.

Best Answer


Found the solution: You need to do a < /dev/null after the PHP command:

php -r 'for ($i=0; $i<300; $i++) { print "$i\n";}' < /dev/null | less

Apparently PHP behaves differently because it still expects input from stdin.
With the < /dev/null you force PHP into thinking there is no further input.

Edit 2:

If you don't want to (keep) typing the < /dev/null you can create an alias for php2 or something:

alias php2="php < /dev/null`

You can make this permanent if you add it in your ~/.bashrc.

Now you can do:

php2 -r 'for ($i=0; $i<300; $i++) { print "$i\n";}' | less

You could alias php to itself but then you'll never have the ability to pipe something into php.
You could of course shorten it to p (for less typing).

Original answer:

The bug is also present in CentOS 6.5.

A newly installed CentOS 6.5 has it too (in a VM). A ... | cat | less does not work.
A ... > a && cat a | less does work. Go figure.

Cursor keys also don't work in php --help | less. They do work in python --help | less. So it must be something in the PHP executable. I think this is a longstanding bug in PHP.

I found a reference to this bug here.

Until it is fixed you need to do a redirect:

php -r 'for ($i=0; $i<300; $i++) { print "$i\n";}' > /tmp/php.txt && cat /tmp/php.txt | less