If I define my app configuration
[command]
default=command1
=command2
If command1 fails and command2 succeeds, the task will succeed (according to a quick test). Is there a way to force the task to fail if command1 fails, rather than continue? Or should I be using a completely different approach?
Assuming that command2 might be something complicated like an if clause, and so doing command1 && command2
is not really functional or readable. But on the other hand, replacing the multiline command with a separate script to call seems like overkill. Is there another way?
Rose uses Python’s Popen
to execute the command, unlike Cylc which uses a Bash script with safety rails like set -eu
preconfigured.
Using &&
as you suggested will do the trick.
To make Rose behave like Cylc you could do something like this:
[command]
default=set -euo pipefail
=false
=true
But be aware, this is executed by /bin/sh
which is not necessarily /bin/bash
(see note at the bottom).
Alternatively, when these scripts start to grow in complexity it can be beneficial to define your own wrapper for these commands to run in a shell of your choosing e.g:
# rose-app.conf
[command]
default=my-script
# bin/my-script
#!/usr/bin/env bash
set -euo pipefail
foo "$@"
bar
For more details on the Popen
implementation, I found this helpful snippet in the Python docs:
On POSIX with shell=True
, the shell defaults to /bin/sh
. If args is a string, the string specifies the command to execute through the shell. This means that the string must be formatted exactly as it would be when typed at the shell prompt. This includes, for example, quoting or backslash escaping filenames with spaces in them. If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself. That is to say, Popen
does the equivalent of:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
– subprocess — Subprocess management — Python 3.12.0 documentation