5

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:

10
:j
11

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.
Homepage: http://www.greenwoodsoftware.com/less

$ 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 Terminal.app on Mac OS X to ssh to the box, then running the php command.

Eddified
  • 1,692
  • 1
  • 18
  • 20
  • 1
    Its probably a terminal setting (what does echo $TERM say). I tried the same script in my CentOS 6.2 box and it worked as expected. I wonder if it might be to do with the way your terminal is intepreting CR and LF. What happens if you use "\r\n" rather then just "\n" ? – davidgo Nov 22 '13 at 21:22
  • The $TERM is 'screen'. :) If I try it without screen, it says 'xterm-256color' and still doesn't work right. – Eddified Nov 22 '13 at 22:07
  • Nor Ubuntu 13.04 nor Debian Testing do this. I would blame their less implementation. – Braiam Nov 26 '13 at 00:46
  • What version of CentOS 5 did this work? I'm on 5.9 and it exhibits the same problems you're highlighting for 6.2. – slm Nov 26 '13 at 02:58
  • It is working correctly on my CentOS 5.5 install. – Eddified Nov 26 '13 at 17:13
  • Please could you add following details: `less --version` and `php --version`? PS Could be that PHP recognizes only `php -v` for querying the version number. – t0r0X Dec 02 '13 at 18:12
  • More questions: are you trying this in a terminal window in a graphical environment, directly in a non-graphic console, or via a terminal/ssh/telnet program? – t0r0X Dec 02 '13 at 18:20

2 Answers2

7

Edit:

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
Rik
  • 13,159
  • 1
  • 34
  • 41
  • I had already figured the `... > tmpfile && cat tmpfile | less` workaround on my own... it is a very annoying workaround, but does work. The `< /dev/null` workaround is better but is still only a workaround, but I gave you the bounty for effort. :) – Eddified Dec 02 '13 at 22:52
  • I personally think that while PHP may have a bug here, less *also* has a bug. Usually (i.e. with CentOS 5) when I have a long-running program, less can still be used normally _while_ php continues to produce output. – Eddified Dec 02 '13 at 23:05
  • I added an Edit #2. You can use `alias` (e.g. `php2`) to "ease the pain" :) Did you have the same PHP version (5.3.3 ?) in CentOS 5 as the one in CentOS 6.2? – Rik Dec 02 '13 at 23:13
  • No, I had a different php version before (5.1). – Eddified Dec 03 '13 at 00:16
  • I guess we need someone with a RPM install of PHP 5.3.28+ on CentOS 5 to test this. Or a PHP 5.1.x install on CentOS 6.2+. – Rik Dec 03 '13 at 00:42
  • It **definitively** a PHP issue. I made a snapshot of my CentOS 6.5, removed PHP 5.3.3, installed a RPM of PHP 5.2.17 (and its dependencies) and the problem was **solved**. After re-installing the standard package from CentOS 6.5 again (PHP 5.3.3) the problem was there again. So this problem surfaces between version 5.2.17 and 5.3.27 of PHP. – Rik Dec 03 '13 at 08:07
2

This is a weird behaviour, hard to reproduce... Have you tried setting TERM to plain xterm

export TERM=xterm

or vt100?

export TERM=vt100

Try to manually set the window size (number of lines to scroll, usually == number of lines of your window/console):

...| less --window=80

or try

... |less --raw-control-chars

or

... |less --RAW-CONTROL-CHARS

PS Oh, by the way, CentOS 6.2 was release in June 2012, have you thought about an upgrade to a newer version? The current CentOS version is 6.5 ...

t0r0X
  • 209
  • 1
  • 7