3

I'm at a point in a project where I need to call system commands. I originally started looking at NSTask (as that seems to be the most popular approach) but recently i just came across the system command. It looks like a far easier setup that NSTask. I've seen some questions/answers that say NSTask is the better approach, but I don't see

  1. What are the advantages/disadvantages between the two
  2. In what cases would one more likely to be used than the other

Any help/links/thoughts/ideas? (and yes.. i did a google search)

Just a coder
  • 15,480
  • 16
  • 85
  • 138

2 Answers2

10

NSTask:

  • Can run his task in the background. Allows you to send interrupts and kills to the underlying process, and allows you to suspend or resume the underlying process without setting up threads yourself. Can also run synchronously if that's what you want.
  • Let's you work back and forth with Cocoa classes, like NSStrings without having to do a buncha conversions.
  • Let's you set I/O streams for the underlying process that differ from the caller's.
  • Better supported across all Apple platforms (like iOS) than system(3) -- I don't think system even works on iOS.
  • Requires Cocoa and Objective-C.
  • Doesn't interpret shell arguments or do path expansions of arguments.

system(3):

  • Better supported across all Unix-like platforms.
  • Can run a task with a one-liner.
  • Only requires C.
  • Runs in a shell and will interpret working directory and arguments like /bin/sh would.

For a Cocoa app I always use NSTask; I only use system if I'm doing something that must be C-only or I know will have to run under non-Mac environments. As it is, system is pretty brittle and the more robust solution is doing a fork-exec, because it allows you more control over streams and concurrent operation.

iluvcapra
  • 9,436
  • 2
  • 30
  • 32
  • 1
    Good answer-- +1. A point of clarification: you can't really `fork-exec` a Cocoa process without serious risk. It works, but it is very brittle (`NSTask` does a bunch of stuff in the implementation to avoid this brittleness). – bbum May 13 '13 at 20:26
  • Yeah I'd never fork-exec anything under Cocoa, it's only an option if we're forsaking it from the outset. – iluvcapra May 13 '13 at 20:29
  • @bbum Do you have a reference to explain why fork/exec is brittle ? – koan Jun 24 '13 at 10:05
  • @koan There are various warnings spread around the docs. A `fork` followed by an immediate `exec` is *mostly* supported, but you are much better off going through `NSTask`, which does some internal shenanigans to make it safe. Better still is writing a helper daemon that you communicate with via XPC. Launching a new, small, task is much more efficient. – bbum Jun 24 '13 at 15:17
9

There are some differences. For some of them it is probably har to say in general, whether it is an advantage or not.

  • system() starts a shell. NSTask don't.
  • system() blocks. NSTask run asynchronously.
  • system() only takes args. NSTask works with pipes.
  • system() has only an integer exit code. NSTask works with pipes. (Yes, mentioned again. This is for output.)
  • system() takes a complete command line. To NSTask args can be passed in an array.
  • system() runs on the current directory. To NSTask you can pass a working directory.

This are some differences out of my mind without rechecking the documentation. It is an overview.

Amin Negm-Awad
  • 16,582
  • 3
  • 35
  • 50
  • 1
    2 answers, cant choose both. Other response went in bit more in dept. Gave you +1 – Just a coder May 13 '13 at 21:38
  • @AminNegm-Awad I just stumbled across your answer and it saved me a couple of hours. When you come back I have a nice story to tell. Can't upvote your answer enough. Everyone should have to memorize your six facts above. – Christian Kienle Jan 12 '14 at 14:21