First off I submitted a bug report at https://developer.apple.com/bug-reporting/
Using Xcode 11.3 and command line utilities.
Bug: "codesign" command line utility always prints to stderr.
This confused me while I was trying to test that codesigning succeeded as part of a continuous integration script.
NOTE that you may use the codesign return value to test success or failure.
Workaround: One liner to save only stderr output from a command to a variable and print stdout:
{ stderr_only="$( { codesign ${=CSVARS} $SIG "$APP_NAME"; } 2>&1 1>&3 3>&- )"; } 3>&1;
ret_val=$?
echo "Return val: $ret_val"
echo "Codesign stderr only: $stderr_only"
Script to reproduce
#!/bin/zsh
#codesign_prints_to_stderr.sh
export CSARGS="-f --verbose --timestamp -o runtime --sign "
#NOTE: Replace with a valid signature
export SIG="Developer ID Application: Your Company (ID)"
#NOTE: Replace with a valid app folder
export APP_NAME="TestApp.app"
echo "codesign ${=CSARGS} $SIG \"$APP_NAME\""
unset save_stdout save_stderr save_return_val
eval "$( ( codesign ${=CSARGS} $SIG "$APP_NAME" ) \
2> >(save_stderr=$(cat); typeset -p save_stderr) \
> >(save_stdout=$(cat); typeset -p save_stdout); save_return_val=$?; typeset -p save_return_val )"
echo "Return Value: $save_return_val"
echo "Saved stdout: $save_stdout"
echo "Saved stderr: $save_stderr"
echo "codesign -dvvv \"$APP_NAME\""
unset save_stdout save_stderr save_return_val
eval "$( ( codesign -dvvv "$APP_NAME" ) \
2> >(save_stderr=$(cat); typeset -p save_stderr) \
> >(save_stdout=$(cat); typeset -p save_stdout); save_return_val=$?; typeset -p save_return_val )"
echo "Return Value: $save_return_val"
echo "Saved stdout: $save_stdout"
echo "Saved stderr: $save_stderr"
Example output.
1. Success: Nominal case prints to stderr:
./codesign_prints_to_stderr.sh
codesign -f --verbose --timestamp -o runtime --sign Developer ID Application: Your Company (ID) "TestApp.app"
Return Value: 0
Saved stdout:
Saved stderr: TestApp.app: signed app bundle with Mach-O thin (x86_64) []
2. Error case: FakeApp doesn't exist
./codesign_prints_to_stderr.sh
codesign -f --verbose --timestamp -o runtime --sign Developer ID Application: Your Company (ID) "FakeApp.app"
Return Value: 1
Saved stdout:
Saved stderr: FakeApp.app: No such file or directory
3. Error case: Developer ID doesn't exist
./codesign_prints_to_stderr.sh
codesign -f --verbose --timestamp -o runtime --sign Developer ID Application: FakeID (FAKE) "TestApp.app"
Return Value: 1
Saved stdout:
Saved stderr: Developer ID Application: FakeID (FAKE): no identity found
4. Error case: App already signed:
./codesign_prints_to_stderr.sh
codesign --verbose --timestamp -o runtime --sign Developer ID Application: Your Company (ID) "TestApp.app"
Return Value: 1
Saved stdout:
Saved stderr: TestApp.app: is already signed
5. Success: force re-sign the app:
./codesign_prints_to_stderr.sh
codesign -f --verbose --timestamp -o runtime --sign Developer ID Application: Your Company (ID) "TestApp.app"
Return Value: 0
Saved stdout:
Saved stderr: TestApp.app: replacing existing signature
TestApp.app: signed app bundle with Mach-O thin (x86_64) []
6. Example "-d" output also goes to stderr:
codesign -dvvv "TestApp.app"
Return Value: 0
Saved stdout:
Saved stderr: Executable=/Users/YourName/Projects/testApp/TestApp.app/Contents/MacOS/TestApp
Identifier=
Format=app bundle with Mach-O thin (x86_64)
CodeDirectory v=20500 size=332 flags=0x10000(runtime) hashes=4+3 location=embedded
Hash type=sha256 size=32
... (rest is all in stderr)