342

What are the differences?

Is there a specific situation or reason for each function? If yes, can you give some examples of those situations?

PHP.net says that they are used to execute external programs. see reference From the examples I see, I don't see any obvious difference.

If I were to simply run a script (bash or python), which function do you recommend me to use?

jww
  • 97,681
  • 90
  • 411
  • 885
codingbear
  • 14,773
  • 20
  • 48
  • 64
  • 21
    There's also `proc_open()` and `popen()`, both of which allow a higher degree of control over the spawned process. – Christian Sep 18 '11 at 10:03

5 Answers5

217

They have slightly different purposes.

  • exec() is for calling a system command, and perhaps dealing with the output yourself.
  • system() is for executing a system command and immediately displaying the output - presumably text.
  • passthru() is for executing a system command which you wish the raw return from - presumably something binary.

Regardless, I suggest you not use any of them. They all produce highly unportable code.

ZioCain
  • 429
  • 9
  • 27
Kalium
  • 4,662
  • 2
  • 18
  • 17
  • 168
    Sometimes portability has to be sacrificed for functionality. There are some things PHP just can't do well. – Frank Crook Apr 09 '09 at 05:10
  • 32
    @Kalium: can you elaborate more on your statement? just stating some vague percentage statistics does not convince me. I believe that using system calls to execute scripts are totally fine as long as the whole application does not depend one a bunch of scripts in the back-end. – codingbear Apr 09 '09 at 07:01
  • 2
    @bLee In actual usage, I typically see system calls used to do little things like ls, cp, mv, and zip calls instead of anything that might genuinely justify it like a script invocation. – Kalium Apr 09 '09 at 07:10
  • 4
    @Frank Crook *There are some things PHP just can't do well* - that's why we have modules for PHP and APIs. Using system calls is archaic way, using API is more civilized. – OZ_ Sep 18 '11 at 07:35
  • 46
    @Christian `izkata@izein:~$ dir -bash: dir: command not found` - FreeBSD – Izkata Apr 10 '12 at 19:05
  • 2
    By *"all OSes"*, I might have left out FreeBSD accidentally. Sorry. **:)** – Christian Apr 11 '12 at 07:17
  • 5
    @OZ_ I've come to the situation where I had to do very expensive computations. No PHP-Module were (is) available for that. I wrote my own C program and I invoke it with passthru(). Sometimes portability can be less important than other things. Depends on the project. – Paolo May 27 '13 at 20:36
  • 1
    @Paolo but it's only exception, not rule ;) – OZ_ May 27 '13 at 23:59
  • 5
    'Highly unportable' code, as well as 'more likely to be vulnerable to code injection' code. Sometimes it's necessary, but executing the task in PHP is preferable if possible. – siliconrockstar Dec 30 '13 at 16:25
  • 2
    @Christian it's not there in OS X either. :) – Fuzzy76 Jan 24 '14 at 13:08
  • 7
    @Kalium "... 95% of the time people want to use a shell call, the reasons are all wrong..." I think is very subjective this approach, would you mean all programmers, devops, sysadmins should think the same way, do the same thinks on the same path?. Where is freedom?. I think there is no "Wrong" approach, but rather there are "Better" ways to deal every specific problem. – Frederic Yesid Peña Sánchez Jan 29 '15 at 17:07
  • 4
    Just because something isn't portable doesn't make it wrong. I for example needed a way to run wget to make a static copy of a site via a web interface.. this might be pretty hard if I can't run programs.. – John Hunt Sep 16 '15 at 14:43
  • 3
    @Kalium, In many cases system commands are used when PHP is acting as an interface to other apps. E.g. [pentest-tools](https://goo.gl/jorRi0) is a webapp that provides an interface to well known security tools like nmap, nessus, nikto and etc. Rewriting those apps in PHP is **problematic**, not just because of enormous time needed, but because they will not behave in completely identical ways. Even without bugs, the rewritten app will not be identical to the original app and this makes diagnostics a headache. – Pacerier Feb 24 '16 at 15:06
  • 11
    Also, it's a **fallacy** to think that PHP is portable as long as you avoid `exec`, `system`, `passthru`. PHP code is reliant on the environment it runs in, and many security bugs are due to not having this in consideration. Here's a quick example: http://stackoverflow.com/questions/3003145/how-to-get-the-client-ip-address-in-php#comment50230065_3003233 – Pacerier Feb 24 '16 at 15:06
  • 5
    Not everyone's project requires them to execute on multiple OSs. I couldn't care less whether my PHP runs under Windows, we control the environment and we aren't giving our code out for others to use. – dougd_in_nc Mar 11 '18 at 03:12
  • From a security standpoint, all are very dangerous. https://www.eukhost.com/blog/webhosting/dangerous-php-functions-must-be-disabled/ – jarrodwhitley Feb 15 '19 at 21:40
152

The previous answers seem all to be a little confusing or incomplete, so here is a table of the differences...

+----------------+-----------------+----------------+----------------+
|    Command     | Displays Output | Can Get Output | Gets Exit Code |
+----------------+-----------------+----------------+----------------+
| system()       | Yes (as text)   | Last line only | Yes            |
| passthru()     | Yes (raw)       | No             | Yes            |
| exec()         | No              | Yes (array)    | Yes            |
| shell_exec()   | No              | Yes (string)   | No             |
| backticks (``) | No              | Yes (string)   | No             |
+----------------+-----------------+----------------+----------------+
  • "Displays Output" means it streams the output to the browser (or command line output if running from a command line).
  • "Can Get Output" means you can get the output of the command and assign it to a PHP variable.
  • The "exit code" is a special value returned by the command (also called the "return status"). Zero usually means it was successful, other values are usually error codes.

Other misc things to be aware of:

  • The shell_exec() and the backticks operator do the same thing.
  • There are also proc_open() and popen() which allow you to interactively read/write streams with an executing command.
  • Add "2>&1" to the command string if you also want to capture/display error messages.
  • Use escapeshellcmd() to escape command arguments that may contain problem characters.
  • If passing an $output variable to exec() to store the output, if $output isn't empty, it will append the new output to it. So you may need to unset($output) first.
orrd
  • 9,469
  • 5
  • 39
  • 31
141

As drawn from http://php.net/ && Chipmunkninja:

The system() Function

The system function in PHP takes a string argument with the command to execute as well as any arguments you wish passed to that command. This function executes the specified command, and dumps any resulting text to the output stream (either the HTTP output in a web server situation, or the console if you are running PHP as a command line tool). The return of this function is the last line of output from the program, if it emits text output.

The exec() Function

The system function is quite useful and powerful, but one of the biggest problems with it is that all resulting text from the program goes directly to the output stream. There will be situations where you might like to format the resulting text and display it in some different way, or not display it at all.

For this, the exec function in PHP is perfectly adapted. Instead of automatically dumping all text generated by the program being executed to the output stream, it gives you the opportunity to put this text in an array returned in the second parameter to the function:

The shell_exec() Function

Most of the programs we have been executing thus far have been, more or less, real programs1. However, the environment in which Windows and Unix users operate is actually much richer than this. Windows users have the option of using the Windows Command Prompt program, cmd.exe This program is known as a command shell.

The passthru() Function

One fascinating function that PHP provides similar to those we have seen so far is the passthru function. This function, like the others, executes the program you tell it to. However, it then proceeds to immediately send the raw output from this program to the output stream with which PHP is currently working (i.e. either HTTP in a web server scenario, or the shell in a command line version of PHP).

The proc_open() Function and popen() function

proc_open() is similar to popen() but provides a much greater degree of control over the program execution. cmd is the command to be executed by the shell. descriptorspec is an indexed array where the key represents the descriptor number and the value represents how PHP will pass that descriptor to the child process. pipes will be set to an indexed array of file pointers that correspond to PHP's end of any pipes that are created. The return value is a resource representing the process; you should free it using proc_close() when you are finished with it.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Dinesh Saini
  • 2,917
  • 2
  • 30
  • 48
22

It really all comes down to how you want to handle output that the command might return and whether you want your PHP script to wait for the callee program to finish or not.

  • exec executes a command and passes output to the caller (or returns it in an optional variable).

  • passthru is similar to the exec() function in that it executes a command . This function should be used in place of exec() or system() when the output from the Unix command is binary data which needs to be passed directly back to the browser.

  • system executes an external program and displays the output, but only the last line.

If you need to execute a command and have all the data from the command passed directly back without any interference, use the passthru() function.

kenorb
  • 155,785
  • 88
  • 678
  • 743
Cody Caughlan
  • 32,456
  • 5
  • 63
  • 68
  • Be also aware that exec could do a loop in some versions of php. see https://stackoverflow.com/questions/3615713/exec-cause-an-infinite-loop-of-starting-requested-program – Alexander Behling May 26 '21 at 09:14
10

If you're running your PHP script from the command-line, passthru() has one large benefit. It will let you execute scripts/programs such as vim, dialog, etc, letting those programs handle control and returning to your script only when they are done.

If you use system() or exec() to execute those scripts/programs, it simply won't work.

Gotcha: For some reason, you can't execute less with passthru() in PHP.

the
  • 21,007
  • 11
  • 68
  • 101
Matt
  • 2,229
  • 12
  • 10
  • 1
    I don't understand what you're saying. You can execute programs both from CLI and (F)CGI (as well as mod_php). There may be system-imposed restrictions, such as selinux. But a well set-up system will have those selectively off. Of course a *shared* host is a different story, but you won't offer a *shared* environment to esteemed clients either, no? – Christian Sep 18 '11 at 10:01