IPC::System::Simple is certainly easier to learn and use for simple use cases. It works great for capturing output of a known outcome (e.g. you know the output length or can expect what it looks like).
But when you're not sure what the output could be, or what the size of the output is, it's generally not a good idea to capture everything into a variable for fear that it may consume too much memory.
And if you need to be able to
- fine tune how processes spawn and fork from each other (e.g. fork a process already in the "background" so one can monitor the other),
- or to pipe the output of one process to another just like in a Unix shell (e.g. bash/csh | pipe) while still being interactive like IPC::Open3,
- or to specify some Perl code that will only run in the child process prior to exec-ing without worrying about too much boilerplate code like if (fork) { .. } else { .. }
... for more flexibility, there's
IPC::Exe. The perldoc provides some complex examples of what would traditionally require more than a few external scripts to achieve.