Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ops Shell Scripting

ProdOps
August 09, 2015

Ops Shell Scripting

www.meetup.com/OpsTalk/events/223037611/

How to write bash like a boss (with unitetests and idempotency)

ProdOps

August 09, 2015
Tweet

More Decks by ProdOps

Other Decks in Technology

Transcript

  1. .co.il www. parse invocation arguments while read a line from

    stdin process read line print errors to stderr print output to stdout end exit with return code standard input standard output standard error rc exec + arguments
  2. .co.il www. cmd arg1 arg2 cmd > file cmd >>

    file cmd 2> file cmd < file cmd ; echo $?
  3. .co.il www. if [ "foobar" = "foobar" ] then echo

    "They are equal" else echo "They are not equal" fi
  4. .co.il www. [ "foobar" = "foobar" ] || \ echo

    "They are not equal" [ "foobar" != "foobar" ] && \ echo "They are not equal"
  5. .co.il www. [ "foobar" = "foobar" ] && { echo

    "They are equal" } || { echo "They are not equal" }
  6. .co.il www. | 2 -2 -4 | A = |

    -1 3 4 | | 1 -2 -3 |
  7. .co.il www. | 2 -2 -4 | A = |

    -1 3 4 | | 1 -2 -3 | A2 = ?
  8. .co.il www. | 2 -2 -4 | A = |

    -1 3 4 | | 1 -2 -3 | A2 = A A321 = ?
  9. .co.il www. | 2 -2 -4 | An = |

    -1 3 4 | | 1 -2 -3 |
  10. .co.il www. #!/bin/bash d="/home/evgeny/.ssh" [ -d "$d" ] || {

    mkdir "$d" chown evgeny "$d" chmod u+rwx,go-rwx "$d" }
  11. .co.il www. #!/bin/bash set -o errexit # set -e set

    -o nounset # set -u set -o pipefail IFS="\n\t"
  12. .co.il www. #!/usr/bin/env bats @test "git binary is found in

    PATH" { run "which git" [ "$status" -eq 0 ] } github.com/sstephenson/bats/
  13. .co.il www. git_rev_email() { git rev-list -1 --pretty='format:%ae' "$@" |

    tail -1 } git_rev_name() { git rev-list -1 --pretty='format:%an' "$@" | tail -1 }
  14. .co.il www. email_fmt='^[A-Za-z0-9]\+@..\.example\.com$' validate_email() { local rev=$1; shift local name;

    name=$(git_rev_name "$rev") local email; email=$(git_rev_email "$rev") local ldapname; ldapname=$(ldap_name_from_email "$email") echo "$email" | grep "$email_fmt" >/dev/null || { echo "ERROR: non-company e-mail in commit:" \ "$email in $(git_short_sha1 "$rev")" return 1 } [ "$name" != "$ldapname" ] && { echo "WARNING: name '$name' in commit $(git_short_sha1 "$rev")" \ "differs from '$ldapname' associated with $email" } return 0 }
  15. .co.il www. rev1="a82e0790910f2589373ff34a8416f72f8b25857d" invalid_name="Foo Bar" invalid_email="[email protected]" mock_invalid_name() { assertEquals "$rev1"

    "$1"; echo "$invalid_name"; } mock_invalid_email() { assertEquals "$rev1" "$1"; echo "$invalid_email"; } testBadEmail() { git_rev_name() { mock_invalid_name "$@"; } git_rev_email() { mock_invalid_email "$@"; } ldap_name_from_email() { mock_ldap_valid_name "$@"; } stdout=$( validate_email "$rev1" ) rc=$? assertEquals "invalid email prints an error" \ "ERROR: non-company e-mail in commit: ${invalid_email} in $(git_short_sha1 "$rev1")" \ "$stdout" assertEquals "return code is error" 1 "$rc" } . "$(dirname "$0")/../shunit2"
  16. .co.il www. We invite you to join Operations Israel Facebook

    group on on.fb.me/Ops-IL link to slides dvps.me/ops-shell-scripting Thank you! www.devops.co.il