Expanding on what Quinn said, I did what to explain what's actually going on here as the answer is that, ironically, macOS is basically acting the same way most Unix system would. Let me start here:
The only way I can capture stderr reliably is by bypassing the bundle and directly launching the binary inside with ./MyApp.app/Contents/MacOS/MyApp 2> ~/log.txt
This works because your primary executable is being run in the same way any other Unix tool is.
However, when the app is launched via open MyApp.app, stderr redirection like open MyApp.app 2> log.txt does not capture any output — the file is created, but remains empty.
This fails for two reasons:
-
(minor) What open actually does ask LaunchServices to run your app, making launchd the parent process of your app.
-
(major) You didn't tell "open" to reroute stderr/in/out so it didn't. From the open man page:
--stdin PATH
Launches the application with stdin connected to PATH.
--stdout PATH
Launches the application with stdout connected to PATH.
--stderr PATH
Launches the application with stderr connected to PATH.
Double-clicking the app in Finder also does not show any stderr output.
The Finder is actually doing the same thing "open" does, except it doesn't allow you to specify the same range of options.
In terms of your questions here:
Is there any recommended or supported way to redirect or access stderr output when launching a .app bundle via open,
Setting all other issues aside, any Unix process has control over it's own file handles in including stderr. I don't have a code snippet at hand, but the process involves using the "dup" and "dup2" syscalls to reroute the relevant file handles. The specific code would be exactly the same as basically "any" Unix system. I'm not sure if I'd actually do this, but if you want to, that's what's involved.
or any best practice for logging critical failures from a GUI app when terminal output isn't visible?
os_log is the systems "core" logging API and is where most logg output should already be routed. However, it's extremely powerful and highly customizable. Everything it's capable of is a topic in it's own right, but "Your Friend the System Log" is probably where I would start. One side comment here is that if you do choose to implement your own logging system, I would strongly recommend that you:
-
Make sure your log messages are also logged through os_log to the system log.
-
Make sure that your logging's timestamp format matches as closely as possible what the system logs.
That second point is actually really critical, as one of the most useful ways to debug a complex issue is to have an app level log which you can then correlate with the system log (generally through a sysdiagnose). The app log then services as an "index" into the system log (which shows you what's happening across the broader system). Of course, that process is much harder if the app time stamp isn't accurate enough and/or is formatted in a way that makes it hard to correlate with system log.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware