tags:

views:

292

answers:

11

Why would you prefer to keep from using bash commands via exec() in php?

I do not consider portability issue (I definitely will not port it to run on Windows). That's just a matter of a good way of writing scripts.

On the one hand:

  1. I need to write much more lines in php then in bash to accomplish the same task. For example, when I need to filter some lines in a file, I just can't imaging using something instead of cat file | grep string > new_file. This would take much more time and effort to do in php.
  2. I do not want to analyze all situations when something might go wrong. I will just show bash command output to the user, so he would know what exactly happened.
  3. I do not need to write another wrapper around filesystem functions and use it. It is much more efficient to leverage the OS for file searching, manipulation etc.

On the other hand:

  1. Calling unix command with exec() might be inefficient in most cases. It is quite expensive to spawn a separate process. Not talking about scripts running under apache, which is even much less efficient than spawning from command line scripts.
  2. Sometimes it turns out to be 'black magic-like' and perl-like scripting. Though it can be avoided via detailed comments.
  3. Maybe I'm just trying to use two different tools together when they are not supposed to. Each tool has its own application and should not be mixed together.
  4. Even though I'm sure users will not try to run script will malicious purposes, using exec() is a potential security threat. In most cases user data can be escaped with escapeshellarg(), but it is still an issue to take into account.
+1  A: 

Personally, if portability isn't an issue, I would totally use *nix commands like grep, locate, etc. anyday over trying to duplicate that functionality in PHP.

It's about using the best tool for the job. In some cases, arguably more often than most people realize, it is much more efficient to leverage the OS for file searching, manipulation, etc. (amongst other things)

Dominic Barnes
+1  A: 

Lot of people would descend on your like a ton of bricks for even mentioning using exec. Some people would consider is blasphemy but not me. I can see nothing wrong with exec for some situations if your server has been properly configured. The disadvantage though is that you are spawning another process.

e4c5
The spawning is quite expensive. It is (almost) always *a lot* less efficient than using PHP.
Jacco
I agree that spawning another process is costly.
e4c5
+12  A: 

another reason to avoid this is that it's much easier to create security holes like this. for example, if a user manage to sneak

`rm -rf /`

(With backticks) into the input, your bash code might actually nuke the server (or nuke something at least).

this is mostly a religious thing, most developers try to write code that always works. relying on external commands is a sure way to get your code to fail on some systems (even on the same OS).

Omry
I agree with your last paragraph but I am having difficulties seeing the security hole in the first one, doesn't this only apply when the code is actually executed using eval()?
Pekka
try this one : <?php $INPUT="hello \`ls\`";system("echo $INPUT");?>
Omry
Ahh, that's what you mean. Well, but that's what `escapeshellarg()` is for, isn't it? Or does that not get caught?
Pekka
it just might. until some clever user find a way around it. maybe by getting the generated output to contain backticks and some command. in my opinion it's just a bad thing to use on production. not to mention the performance impact of opening a process (or a few) for something that can trivially be achieved via a function call.
Omry
+7  A: 

What are you trying to achieve? PHP has regex-based functions to find what you need from a file. Yes, you would probably need about 5 lines of code to do it, but it would probably be no more or less efficient.

The main reason against using exec() in PHP is for security. If you're trusting your user to give you a command to exec() in bash, they could easily run malicious commands, such as installing and starting backdoor trojans, removing files, and the like.

As long as you're careful though (use the shell escaping commands to clean user input, restrict the Apache user permissions etc) it shouldn't be a problem. I'm just working on a complete platform at the moment, which relies on the front-end executing shell processes simply because C++ is much faster than PHP, so I've written a lot of the backend logic as a shell application and keep PHP for the front-end logic.

Andy Shellam
+1  A: 

IMHO, the main concern with using exec() to execute *nix commands via PHP is security, more than performance or even code style.

If you have a very good input sanitization (and this is very hard to achieve), you may be able not to have any security hole.

Wookai
+1  A: 

If you are running your PHP using a web server, the "user" that runs the script may not have permission to run certain shell commands. you said portability is not an issue, but i can guarantee to you that it IS an issue, (unless you are creating PHP scripts for fun). In the business world where things and condition changes fast, you won't know you might one day have to run your scripts on other platforms.

A: 

If portability really isn't an issue, because you are building a company solution that is always going to be on your own, totally controlled servers, I say go for shell commands as much as you want to. There is no inherent security problem as long as you do proper basic sanitation using escapeshellarg() and consorts.

At the same time, in my projects portability mostly is an issue, and when it is, I try not to use shell commands at all - only when something can't be done in PHP at all (e.g. MP3 decoding/encoding, ImageMagick, Video operations) or not reasonably (i.e. a PHP based solution is way too slow) will I use external commands.

Pekka
+2  A: 

Even though you say portability isn't an issue, you never know for certain what the future holds, so I'd encourage you to reconsider that position. For example, I was once asked to port an editor that was written (by someone else) from Unix to DOS. The original program wasn't expected to be ported and was written with Unix specific calls deeply embedded in the code. After reviewing the amount of work required, we abandoned the task as too time consuming.

I have used exec calls in PHP; however, I had no other way to accomplish what I needed (I had to call another program written in another language with no other bridge between the languages). However, IMO, exec calls which aren't necessary are ugly. As others have said, they can also create security risks and slow your program down.

As you said yourself, you need to document the exec calls well to be sure they'll be understood by programmers. Why create the extra work? Not just now but in the future, when any changes to the exec call will also need to be documented.

Finally, I suggest you learn PHP and its functions a bit better. I'm not that good with PHP, but in just a matter of minutes with Google and php.net, I think I accomplished the same thing you gave as an example with:

$search_results = preg_grep($search_string, file($file_name));
foreach ($search_results as $result) {
    echo $result . "\n";
}

Yes, it's a bit more code, but not that much, and you can put it in a function if appropriate ... and I wouldn't be surprised if a PHP guru could shorten it.

GreenMatt
I really don't think that I will need to port script to DOS :) But still, what incompatibilities between UNIX-based OS did you face? Do you have some examples that pop up in your mind?
altern
@altern: This was about 20 years ago, so much of this is now a faint (and painful) memory ... Anyway, the Unix version was written using curses, and there wasn't a DOS port of curses yet (or at least we didn't know of one). Thus all the screen stuff, which was not separate from the processing code, would have had to be changed one item at a time, as each item was pretty much unique. I don't recall how many curses calls we found, but it was several hundred, or maybe even a few thousand.
GreenMatt
+1  A: 

php is not a good executor. php spawns a process from apache, and if that process hangs, your apache server will hang, if your site is also running on the same apache; it will fail.

You can expect to have silly issues like these as well, if it happens you can't even restart apache without killing the spawned process manually from shell.

http://bugs.php.net/bug.php?id=38915

therefore, i'm not talking about security, running linux commands from php fails more than you'd think, worst part of using exec, it's not always possible to get error messages back to php. or write subsequent method that depends on what happened with exec.

consider this pseudo example:

exec ('bash myscript.sh',$x)
if (myScriptWasOk == true) then do this

There is no way that you get that 'myScriptWasOk' variable right. You just don't know anything about it, $x will help you sometimes.

All this being said, if u need something simple, and if you tested your script and it works ok, just go for it.

Devrim
I have command line script. Apache has nothing to do with this, fortunately. I certainly would not consider (or think 10 times before) using exec in web-scripts.
altern
i haven't tested php-cli so can't really say much.
Devrim
+1  A: 

It is not secure unless you take extreme precautions to make sure it can't be used by people executing the code.

Petro
+1  A: 

If you are only aiming for Unix compatibility (which is perfectly fine), I can't see anything wrong with it. Virtually server operating system available today is a Unix clone, except of course for Windows which I think is ridiculous to use as a server platform in the first place (and I'm talking from experience here, this is not just Microsoft hatred). Unix-compatibility is a perfectly legitimate requirement on any server in my opinion.

The only real reason I can see to avoid it is performance. You will quickly find that executing external processes in general is extremely slow. It's slow in C, and it's slow in PHP. I would think that's the biggest real, non-religious concern.

EDIT: Oh, and as for the security problem, that's a simple matter of making sure that you are in total control of the variables passed to the operating system. It's a concern you have to make when communicating between processes and languages anyway, for example when you do SQL queries. It's not a big enough reason in my opinion to not do something, it's just something that has to be taken into account in this case, like in every case.

Helgi Hrafn Gunnarsson