Where I work, we're in the process of automating a lot of tasks that currently need to be run manually by an IT person to determine if the next task can be performed (the second task depends on certain outcomes of the first task). We're ending the first phase of our script automation process, having reworked the first task to have better support for logging, error handling and even emailing a report, but we will not be able to get to reworking the second task right away so it will remain in its current state of manual use.

In the meantime, it has been suggested that we implement exit codes into the first task so that we can simply chain the second task, in its current state, on a successful first task. The only issue here is that the first task is a little more complicated than just success/fail. There are many different parts that can pass that will allow the second task to be run a certain way. Now I know none of this is impossible with exit codes. We could take the time to implement the first task to return all these different exit codes so that the second task can be run in a semi-automated fashion based on these exit codes as a temporary solution to making the entire process automated until we have the time to go in and rework the second task the correct way.

My question is, is it practical to take the time to implement exit codes into a script as a temporary solution to a larger problem where the script is more complex than success/fail?

Note: The exit codes will take some time to implement as our rework of the first task was not designed to return exit codes (it is a self-contained script that handles its own logging and error reporting).

Edit: It is a given that we have to go back and rework the second task in a way that the two tasks can be run independently of each other (their outcomes/state will be shared through a database).

Edit: In general, I know it is useful to have exit codes, but my current situation involves spending a considerable amount of development time to go back and implement the exit codes properly (again because the outcome of the script is quite complex with many different levels of success/fail), when they aren't part of the overall solution, but a temporary hack to our new system in order to "fake" it as a completely automated system until we can actually complete the rework. I guess it's more of a "Is the time spent to implement this hack, while not a complete solution, worth it if we have to go back and undo the hack later?" question.

4 Answers 4


Multiple values for exit codes is a pretty common practice within the world of application programming. Take a look at errno.h as an example.

The key part is to coordinate on the meaning of the exit codes so that callers & senders are able to correctly communicate their exit status.

To address some of the particulars of your question:

The only issue here is that the first task is a little more complicated than just success/fail.

Which would be a perfect use case for implementing multiple exit codes as you suggest. Perhaps one of the codes you need is TRY_AGAIN_LATER, which would let your calling routine know that the immediate call had failed, but there's a good chance it would work after a timeout and then retry.

My question is, is it practical to take the time to implement exit codes into a script as a temporary solution to a larger problem where the script is more complex than success/fail?

Absolutely practical and advisable. You're not guaranteed that you'll have the time to fix the 2nd script. And it may actually be easier to just wait and retry once the error condition has passed. "Good enough" may be exactly that in this case - why spend inordinate amounts of time fixing a script when you can just wait out the problem? Granted, that may not be your exact case, but having multiple values in the exit codes buys you that flexibility.

"Is the time spent to implement this hack, while not a complete solution, worth it if we have to go back and undo the hack later?"

Most likely yes, it will still be worth your while.

  1. You're not guaranteed to be given the time later to properly fix the 2nd script.
  2. You're not guaranteed you'll be able to properly fix the 2nd script. Underlying technical issues may prevent your code from working the way you want to.
  3. If you don't implement the "hack" then consider how much you and your team may suffer in the interim keeping the two scripts running.
  4. Properly implemented, the hack shouldn't need to be backed out. Those sections of the first script simply won't get called. And I'm having a hard time seeing how there would be that much work in the 2nd script - you'll be fleshing out the error paths that would have previously returned a more nuanced exit code.
  5. Your scripts are in version control, right? Create a new branch and put the "hacked" scripts in there with the additional exit codes. When you're ready to fix the 2nd script go back to your main branch and work from there.

But take some rough swags at cost to implement the "hack" and costs to undo all of it. Compare that to how much your team will suffer until you have the time to completely fix the 2nd script. That evaluation would end up being your final answer.

  • Thanks for the advice. Yeah I realize that it is possible, and for the foreseeable future it could be a fix, but it is important to note (and maybe I didn't stress this in my post) but we do have to go back and rework the second task as part of our larger project goals, it just isn't in the current scope of our short-term goals.
    – Wes
    Commented Oct 10, 2013 at 16:10
  • @Wes if I had a dollar for every time I head "we have to do X" then I would have retired already. :-) Our field has constantly shifting priorities, so we have to make decisions that protect us in the short term and set us up well for the (hoped for) long term change. Using multiple exit codes would not preclude you from fixing the 2nd script later. It just makes your life a lot easier until you can fix the 2nd script.
    – user53019
    Commented Oct 10, 2013 at 16:52
  • I think I may have oversimplified/overgeneralized my argument. Please see my edit.
    – Wes
    Commented Oct 10, 2013 at 17:18

What you are doing is building a Workflow system, which is really just a complex state machine. Exit codes (and error logging) are very important to informing operations, testing, and development to where things failed (and succeeded). But what you really want is a signaling mechanism that communicates to other entities whether their work can progress, must be delayed, or whether intervention is needed.

Exit codes are one important part of the picture, and can be used as a proxy for solving the workflow issue. But many processes are more complex than a linear flow of work. And often systems are implemented that combine more than one work step - leading to the expansion of error codes. Likely you are also looking at scripts which must check that their needed starting conditions are present. So you have error codes due to state conditions which prevent the part from starting work, plus you have error codes due to failures during processing.

Messaging or signaling of state (another answer mentions using XML/JSON) is far more communicative than a numeric error code (and the conflation of meanings of a limited set of error codes). Having a state or message which communicates that a process is 'ok' to start/trigger is a positive signal to proceed.

All that said, there is a principle called YAGNI (You Aint Gonna Need It), which says to postpone build complexity until there is a clear need for it. Since error/exit codes are an existing mechanism, you might find that they work just fine. My advice is more to suggest an alternative to grow into, should you decide that you need something more.


As GlenH7 pointed out, having multiple possible exit code values is a pretty common practice. However, I'm not sure I would go down that road if I was in your position (which is clearly based on my very limited knowledge of your position).

Automated tests are not humans. I think they work much better and bring much more benefit when things really are black and white (or green and red). Most of unit testing books stress on making tests very simple and predictable for this very reason.

In your case, your first task is rather complex so it could return a whole bunch of different things. But the downstream job really cares about one thing: should I or should I not run?

If your downstream job has a bunch of conditional statements and depending on the exit code of the first job, it would do different things then:

  1. Are you sure you want those conditionals? It makes each test run less predictable. If the goal of this stuff is to verify your software works, maybe same verification pass every single time would be easier to maintain?
  2. What if instead of one downstream job, you had N downstream jobs, where each one would run depending on whether or not its environment was setup properly by the first job. This way you could keep each downstream job's code much smaller, simpler and do the point.

Another thing I would consider is that true or false is definitely very limiting in terms of passing around information. But -127 to 127 isn't that much better. It might work today, but you'll probably hit the limit again. What if instead you passed around XML or JSON. Have the first job run and generate a report of what it did. Save that report to a file and have the downstream job parse and base its decision on that. Both XML and JSON formats are extensible so a) you'll be able to use that report for reporting and b) you'll be able to modify job A and extend information it returns, but job B should still be able to consume existing fields that it relies on.


I would stick to the exit codes of task1 giving pass or how it failed info. No more.

Task2 should have a pre-task written that parses the output logs etc of task1 amongst other sources to make the decision of if task2 should run (and maybe what it should run on)..

With a bit of practice, you can keep edits to task1 and task2 to a minimum (or no changes at all). That would be re-use but in a modified flow, so the flow with the task2 pre-condition tester would still need testing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.