Recently I had to deal with a PHP script that was designed to run as a cron job. It does a simple processing: gets some data, creates a CSV file and sends the file using email.
When I manually ran it on the development environment everything went well except for the email not being sent and this strange line of text sneaked in the script’s output:
sh: 1: -t: not found
The email not being sent wasn’t a surprise, I knew that for some (technical or business) reason, the PHP code is unable to send emails from that particular machine. The strange error message (strange for me) is a different story. It was not generated by my code or by any of its dependencies.
Sure, a quick search on Google could bring some light over the mystery; this is how you reached this page, isn’t it?
Eventually I discovered the root cause of the problem by getting PHP info from the command line.
$ php -i | grep sendmail sendmail_from => no value => no value sendmail_path => -t -i => -t -i Path to sendmail => -t -i
The email is not sent because the property
sendmail_from is not set in
The fix is really easy: open
/etc/php.ini, search for key
sendmail_path and make sure it reads:
sendmail_path=sendmail -t -i
Additional or different parameters can be added after the command name (
sendmail). If you use
a different mail program on your system (
postfix or something else) then replace
sendmail with the
name of the mail program you use. This is usually not necessary because most of the alternative mail programs
create a link called
sendmail that points to the actual mail program (for compatibility.)
However, what is the meaning of each component of the error message?
I peeked into the source code of PHP (version 5.4.16) on GitHub and this is what I found. The code that handles
a call to the
mail() function is located in file ext/standard/mail.c.
On line 324 it reads:
Several lines above, the variable
sendmail_cmd is initialized with the value of
sendmail_path defined in
by the value of the 5th parameter of function
mail(), if provided (its name is
In my case, the first parameter of
-t -i (no extra parameters were provided on the call to
Who is popen() and what does it do for a living?
popen() is a system function from the standard C library. Details can be found by running
man popen in an Unix/Linux shell.
See some relevant fragmens below:
SYNOPSIS FILE * popen(const char *command, const char *mode); DESCRIPTION The popen() function ``opens'' a process by creating a bidirectional pipe, forking, and invoking the shell. ... The `command` argument is a (...) string containing a shell command line. This command is passed to `/bin/sh`, using the `-c` flag; interpretation, if any, is performed by the shell.
popen() creates an instance of the classic Bourne shell
/bin/sh and tells it to run the command
I tried this on the devel machine:
axiac:~$ /bin/sh $ -t -i sh: 1: -t: not found
Et voilà! The error message is there!
I ran this command on several other Linux/Unix systems (including a Mac OS X Lion) and some of them provided the same
output while on the others the
1: part was missing. Further investigation revealed that on some of the systems that
produce the error message containing the
/bin/sh is, in fact,
I run several other commands on
dash’s command line and I found out that
1: is the number of the command
it (attempted to) ran since it started.
I never worked with
dash before (except when I thought
/bin/sh is a symlink to
bash and in fact it was
I cannot tell why
dash numbers the commands it runs and how can it be configured to do (or to not do) it so.
Investigating this cryptic error message we found some interesting things about the implementation of PHP. On a Linux/Unix
system there are at least three ways to launch another program:
popen(). By default,
reads the message to send from
STDIN. From the three methods above,
popen() is the easiest (and the most natural) way
sendmail and pass some text to it.
More than that, because
popen() doesn’t run the command by itself but passes it to a shell instance, this approach provides
higher flexibility on defining the command used to send emails from PHP.
The first token of
sendmail_path configuration value can be a shell alias, a shell function, a pipe of commands, a list of commands
or even a small script.