Aside from the aforementioned IPC::System::Simple, I also wrote IPC::System::Options which:
- unlike IPC::System::Simple, provides an interface that is backward-compatible with the built-in system() and readpipe() (backtick), meaning that if you use them like the built-in, they will behave the same;
- provides option (either on a per-call basis, or on a per-import basis) to always try to avoid the shell, or to always try to use the shell;
- provide a bunch of other options, e.g.: to die on failure, to log using Log::ger, to capture or tee output, to set environment variables, to chdir() first, and to run in dry-run mode.