0

I am writing a set of bash scripts.

The first, wrapper calls two scripts: do_something and do_something_else.

In pseudo code:

$ wrapper
do_something
if exitcode of do_something = 0 then 
    do_something_else
else
    exit with error
fi

exit success

This would generate a log file:

$ cat /var/logs/wrapper.log | tail -3
Deleting file 299
Deleting file 300
wrapper ran successfully on 01/01/18 00:01:00 GMT

I have two goals:

  1. create a log of the entire process. In other words, everything thatdo_something, do_something_else and wrapper send to stdout and stderr I want in one log file that shows the daily run of this script so I can grep for errors.
  2. I want to pre-compile do_something, do_something_else and wrapper so I can put them in /usr/bin and scp them to all my systems. This way I have one source in dev and quick running un-editable code in prod.

Is this possible?

8
  • 1
    You want to compile a script? Maybe you've selected the wrong language in which to implement your solution. – Andy Dalton Dec 12 '17 at 17:45
  • Yes, it's possible, but if you just use functions, there's no need for the fancy terminology, block 1 launches block two, on success, launch block 3, block 1 initiates logging. Blocks 2 and 3 log. I think you're maybe confusing yourself needlessly by the language you are using to describe the problem. There's no need to have 3 scripts, that is, 1 script is fine. This is assuming you're creating script 1 2 and 3 and they aren't some other part of the system. I assume by compile you mean put into one file. – Lizardx Dec 12 '17 at 17:48
  • @Andy Dalton I realize this this is not really a compile language. I was thinking along the lines of "base64 -w0" or maybe some simple byte code command – Marinaio Dec 12 '17 at 18:03
  • @Lizardx The reason for calling each is because we wanted to be able to run these blocks autonomously, as well. One script will compress (amongst other things) and it would be nice to use that for other purposes outside of wrapper. By "compile" I meant each of the two scripts and then then compile the wrapper. – Marinaio Dec 12 '17 at 18:04
  • 1
    Make the script functions. Pass the script arguments to launch either the primary block2/block3 or block 2 or block 3. Block 1 takes the script start args, and decides what action to take, running block 2, block 3, or blocks 2 and 3. LIke: script_name 'arg1' 'arg2' etc. Don't think of a script as a series of one liners, make it all functions, which wrap the logic blocks, then you can use it any way you want. If you do it that way, you can extend the functionality almost endlessly without having many small scripts etc. You can also source each sub script into the main to keep the code separate. – Lizardx Dec 12 '17 at 18:55
0

Here's a sample of how to handle this scenario in one script, without losing the functionality that the OP wants, which is:

  1. ability to run multiple blocks of logic, all of them, at once, or one at a time.

  2. Ability to log these actions to a file.

This is a simple example. If you treat the scripting language like you would any other language, and write organized code, suddenly you can do all kinds of stuff with it. The trick is to not leave blocks of loose logic outside of functions, that way you can switch the stuff easily, use one piece, not the other, debug sections, add a logging function, which is what I'd do usually, error_handler(), and so on. With almost no extra work, that is, you end up with a simple but clean and easy to maintain application, not a bunch of lines of random actions stacked on top of each other.

file: my_stuff

#!/usr/bin/env bash

logfile='logfile.log'

function main() {
  case "$1" in
    run-all)
      block_1
      block_2
      ;;
    run-1)
      block_1
      ;;
    run-2)
      block_2
      ;;
    *)
      echo 'No start option provided. Exiting'
      exit 1
      ;;
  esac
}
function block_1(){
  do_something

  if [ "$?" == 0 ]; then 
    do_something_else
    echo "Deleting file 299" >> $logfile
    echo "Deleting file 300" >> $logfile
    echo "wrapper ran successfully on 01/01/18 00:01:00 GMT" >> $logfile
  else
    exit "$?"
  fi
}
function block_2(){
  do_something

  if [ "$?" == 0 ]; then 
    do_something_else
    echo "Deleting file 299" >> $logfile
    echo "Deleting file 300" >> $logfile
    echo "wrapper ran successfully on 01/01/18 00:01:00 GMT" >> $logfile
  else
    exit "$?"
  fi
}
# $@ is the list of start arguments, which main will use
# with $1, $2, and so on.
main $@

You'd run this like so:

./my_stuff 'run-all'

This is of course just an example, but really all you do is organize the logic, arrange it the way you'd do with any language, and then trigger the desired actions. I find that if I start shell scripts assuming they will be used and maintained, and if I write them using functions, then they are as flexible and easy to maintain as any other programming I do.

0

About the everything to a log file part: use exec to redirect stdout & stderr, here date is used to put the date on the log file name:

#!/bin/bash
exec > /somedir/somelog.$(date +%F)
exec 2>&1

# output goes to the log file even if this is an external command
somecmd...     

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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