I have a script that is designed to be run both as a web page, and via the console.
Detecting which method was used to invoke the script seems pretty straight forward, but when the script is being run from the console, I need to know if the script is being run interactively or not (user typing commands, or input redirected from a file).
php script.php
versus
php script.php < input_file
Is this possible?
I also needed a slightly more flexible solution than posix_isatty
that could detect:
After a bit of experimenting and digging around through libc headers, I came up with a very simple class that can do all of the above and more.
class IOMode
{
public $stdin;
public $stdout;
public $stderr;
private function getMode(&$dev, $fp)
{
$stat = fstat($fp);
$mode = $stat['mode'] & 0170000; // S_IFMT
$dev = new StdClass;
$dev->isFifo = $mode == 0010000; // S_IFIFO
$dev->isChr = $mode == 0020000; // S_IFCHR
$dev->isDir = $mode == 0040000; // S_IFDIR
$dev->isBlk = $mode == 0060000; // S_IFBLK
$dev->isReg = $mode == 0100000; // S_IFREG
$dev->isLnk = $mode == 0120000; // S_IFLNK
$dev->isSock = $mode == 0140000; // S_IFSOCK
}
public function __construct()
{
$this->getMode($this->stdin, STDIN);
$this->getMode($this->stdout, STDOUT);
$this->getMode($this->stderr, STDERR);
}
}
$io = new IOMode;
Some example usage, to show what it can detect.
Input:
$ php io.php
// Character device as input
// $io->stdin->isChr == true
$ echo | php io.php
// Input piped from another command
// $io->stdin->isFifo == true
$ php io.php < infile
// Input from a regular file (name taken verbatim from C headers)
// $io->stdin->isReg == true
$ mkdir test
$ php io.php < test
// Directory used as input
// $io->stdin->isDir == true
Output:
$ php io.php
// $io->stdout->isChr == true
$ php io.php | cat
// $io->stdout->isFifo == true
$ php io.php > outfile
// $io->stdout->isReg == true
Error:
$ php io.php
// $io->stderr->isChr == true
$ php io.php 2>&1 | cat
// stderr redirected to stdout AND piped to another command
// $io->stderr->isFifo == true
$ php io.php 2>error
// $io->stderr->isReg == true
I've not included examples for links, sockets, or block devices, but there's no reason they shouldn't work, as the device mode masks for them are in the class.
(Not tested on Windows - mileage may vary)
posix_isatty()
if (posix_isatty(0)) {
// STDIN is a TTY
} else {
// STDIN is a pipe or has no associated TTY
}
Obviously this only works on POSIX compliant operating systems, where PHP has the posix
extension installed. I am not aware of a Windoze equivalent.
For Windows, you can use this:
$b = stream_isatty(STDIN);
if ($b) {
echo "php script.php\n";
} else {
echo "php script.php < input_file\n";
}
https://php.net/function.stream-isatty
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With