| Line 1: |
Line 1: |
| − | == BASH Script ==
| + | '''BASH Scripting''' |
| − | === Hello World ===
| + | ==Hello World== |
| | <source lang="bash"> | | <source lang="bash"> |
| | #!/bin/bash | | #!/bin/bash |
| Line 7: |
Line 7: |
| | </source> | | </source> |
| | | | |
| − | === Variables ===
| + | ==Variables== |
| − | ==== Local Variables ====
| + | ===Local Variables=== |
| | <source lang="bash"> | | <source lang="bash"> |
| | #!/bin/bash | | #!/bin/bash |
| Line 20: |
Line 20: |
| | echo $HELLO | | echo $HELLO |
| | </source> | | </source> |
| − | ==== Boolean ====
| + | ===Boolean=== |
| | + | <source lang="bash"> |
| | #!/bin/bash | | #!/bin/bash |
| | the_world_is_flat=true | | the_world_is_flat=true |
| Line 27: |
Line 28: |
| | echo 'Be careful not to fall off!' | | echo 'Be careful not to fall off!' |
| | fi | | fi |
| | + | </source> |
| | + | |
| | + | ==Print== |
| | + | ===Print to stderr=== |
| | + | f_pinta_error () { |
| | + | v_TIMESTAMP=$(date +${v_FORMATO_TIMESTAMP}) |
| | + | >&2 echo "${v_TIMESTAMP} $1" |
| | + | } |
| | + | |
| | + | ==Strings== |
| | | | |
| − | === Strings ===
| + | ==Loops== |
| − | === Loops ===
| + | ===While=== |
| − | ==== While ====
| |
| | <source lang="bash"> | | <source lang="bash"> |
| | #!/bin/bash | | #!/bin/bash |
| Line 40: |
Line 50: |
| | </source> | | </source> |
| | | | |
| − | ==== For ====
| + | ===For=== |
| | <source lang="bash"> | | <source lang="bash"> |
| | #!/bin/bash | | #!/bin/bash |
| Line 48: |
Line 58: |
| | </source> | | </source> |
| | | | |
| − | === Conditional === | + | Example: git pull from all repositories in a pwd |
| − | ==== if ==== | + | <source lang="bash"> |
| | + | for i in $( ls ); do cd $i; git pull; cd ..; done |
| | + | </source> |
| | + | |
| | + | ===C-like for=== |
| | + | <source lang="bash"> |
| | + | #!/bin/bash |
| | + | for i in `seq 1 10`; |
| | + | do |
| | + | echo $i |
| | + | done |
| | + | </source> |
| | + | ===Loop files=== |
| | + | while read p; do echo $p|underscore pretty ; done < /tenkaichi/boo/done/krilin_2017-12-21T12:45:29.544997.jl.boo |
| | + | |
| | + | ===Loop files in directory=== |
| | + | With paths: |
| | + | <source lang="bash">for filename in /usr/bin/*; do echo $filename; done</source> |
| | + | Without path: |
| | + | <source lang="bash">for i in $(ls /usr/bin);do echo $i; done;</source> |
| | + | |
| | + | ===Until=== |
| | + | <source lang="bash"> |
| | + | #!/bin/bash |
| | + | COUNTER=20 |
| | + | until [ $COUNTER -lt 10 ]; do |
| | + | echo COUNTER $COUNTER |
| | + | let COUNTER-=1 |
| | + | done |
| | + | </source> |
| | + | |
| | + | ==Conditional== |
| | + | ===if=== |
| | <source lang="bash"> | | <source lang="bash"> |
| | #!/bin/bash | | #!/bin/bash |
| Line 61: |
Line 103: |
| | </source> | | </source> |
| | | | |
| − | ==== case ====
| + | ===case=== |
| | <source lang="bash"> | | <source lang="bash"> |
| | #!/bin/bash | | #!/bin/bash |
| Line 69: |
Line 111: |
| | * ) echo "Elije y/n";; | | * ) echo "Elije y/n";; |
| | esac | | esac |
| | + | |
| | + | #!/bin/bash |
| | + | # naclient <login|logout|status|guistatus> [-profile <profile name>] [ -user <user-name>] [-password <password>] |
| | + | |
| | + | |
| | + | function start_vpn(){ |
| | + | naclient login -profile Multi-OS -user xe54512 -password ******* |
| | + | } |
| | + | |
| | + | |
| | + | function stop_vpn(){ |
| | + | naclient logout |
| | + | } |
| | + | |
| | + | function status_vpn(){ |
| | + | naclient status |
| | + | } |
| | + | |
| | + | case $1 in |
| | + | start ) start_vpn;; |
| | + | stop ) stop_vpn;; |
| | + | status ) status_vpn;; |
| | + | * ) echo "Unknown command";; |
| | + | esac |
| | + | |
| | </source> | | </source> |
| | | | |
| − | === User Input ===
| + | ==User Input== |
| | <source lang="bash"> | | <source lang="bash"> |
| | #!/bin/bash | | #!/bin/bash |
| Line 82: |
Line 149: |
| | esac | | esac |
| | done | | done |
| | + | </source> |
| | + | ===Password prompt=== |
| | + | <source lang="bash"> |
| | + | read -s -p "Password: " PASSWORD |
| | </source> | | </source> |
| | | | |
| − | === Arrays ===
| + | ==Arrays== |
| | <source lang="bash"> | | <source lang="bash"> |
| | ARRAY=(one two three) | | ARRAY=(one two three) |
| Line 103: |
Line 174: |
| | </source> | | </source> |
| | | | |
| − | === Functions ===
| + | ==Functions== |
| | <source lang="bash"> | | <source lang="bash"> |
| | function quit { | | function quit { |
| Line 116: |
Line 187: |
| | echo foo | | echo foo |
| | </source> | | </source> |
| − | === extras === | + | |
| − | ==== Check if a package is installed ==== | + | return can only be an integer between 0-255 (0=success); to get the return value (if you just want to return an integer 0-255) is $?<br /> |
| | + | To return something else use echo so output can be captured with $(func)<br /> |
| | + | fun1 || fun2 will only run fun2 if fun1 returns a 0 value<br /> |
| | + | |
| | + | ==Redirections== |
| | + | ===stdout 2 file=== |
| | + | ls -l > ls-l.txt |
| | + | ===stderr 2 file=== |
| | + | grep da * 2> grep-errors.txt |
| | + | ===stdout 2 stderr=== |
| | + | grep da * 1>&2 |
| | + | ===stderr 2 stdout=== |
| | + | grep * 2>&1 |
| | + | ===stderr and stdout 2 file=== |
| | + | rm -f $(find / -name core) &> /dev/null |
| | + | ==Extras== |
| | + | |
| | + | ===Killswitch When ssh user logs in=== |
| | + | <syntaxhighlight lang="bash"> |
| | + | #!/bin/bash |
| | + | ME=10.0.253.131 |
| | + | |
| | + | while true; do |
| | + | OTHER=$( who | grep -v tmux | grep -v ${ME} ) |
| | + | if [ -z "${OTHER}" ]; then |
| | + | echo "No one" |
| | + | else |
| | + | tmux kill-session -t test |
| | + | fi |
| | + | sleep 5 |
| | + | done |
| | + | </syntaxhighlight><br /> |
| | + | ===Set files and folder permissions=== |
| | + | <syntaxhighlight lang="bash"> |
| | + | #!/bin/sh |
| | + | # syntax: setperm.s destdir |
| | + | # |
| | + | |
| | + | destdir=/var/www/rrahome |
| | + | |
| | + | dirmode=0770 |
| | + | filemode=0660 |
| | + | |
| | + | find $destdir -type f -exec chmod ${filemode} {} \; |
| | + | find $destdir -type d -exec chmod ${dirmode} {} \; |
| | + | </syntaxhighlight> |
| | + | |
| | + | ===Backup Hard Drive=== |
| | + | <source lang="bash">#!/bin/bash |
| | + | USAGE="./$(basename ${0}) UUID output_filename" |
| | + | BACKUP_ROOT=/mnt/backup |
| | + | |
| | + | if [ -z "${1}" ]; then |
| | + | echo ${USAGE} |
| | + | exit |
| | + | fi |
| | + | if [ -z "${2}" ]; then |
| | + | echo ${USAGE} |
| | + | exit |
| | + | fi |
| | + | |
| | + | HD=$(blkid | grep $1 | awk -F : '{print $1}') |
| | + | ISO=${BACKUP_ROOT}/$(hostname)/$(date '+%Y/%m')/$2.iso |
| | + | |
| | + | dd if=${HD} of=${ISO} bs=1M</source> |
| | + | |
| | + | ===Extract date from string=== |
| | + | <syntaxhighlight lang="bash"> |
| | + | #!/bin/bash |
| | + | DATE=$( echo ${FILE} | grep -Eo '[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}' ) |
| | + | </syntaxhighlight> |
| | + | |
| | + | ===Ping IP range=== |
| | + | <source lang="bash">#!/bin/bash |
| | + | # cat ping_result.txt | grep ttl | awk '{print $4}' | sed s/:/''/g| sort | uniq |
| | + | BASE=192.168.0. |
| | + | for i in {1..126}; do |
| | + | ping -c 3 ${BASE}$i >> ping_result.txt |
| | + | done</source> |
| | + | ===Check if a package is installed=== |
| | <source lang="bash"> | | <source lang="bash"> |
| | #!/bin/sh | | #!/bin/sh |
| Line 126: |
Line 276: |
| | debInst terminator | | debInst terminator |
| | </source> | | </source> |
| − | ==== Check if a file exists ====
| + | ===Check if a file exists=== |
| | + | <source lang="bash"> |
| | + | if [ -f $FILE1 ] |
| | + | then |
| | + | if [ -f $FILE2 ] |
| | + | then |
| | + | echo OK |
| | + | # MAIN PROGRAM HERE |
| | + | fi |
| | + | fi |
| | + | </source> |
| | + | |
| | + | ===Check if directory exists=== |
| | <source lang="bash"> | | <source lang="bash"> |
| | #!/bin/bash | | #!/bin/bash |
| Line 143: |
Line 305: |
| | </source> | | </source> |
| | | | |
| − | ==== Check user ====
| + | ===Check user=== |
| − | <source lang="bash"> | + | <syntaxhighlight lang="bash"> |
| | + | #!/bin/bash |
| | + | if [ "$EUID" -ne 0 ] |
| | + | then echo "Please run as root" |
| | + | exit |
| | + | fi |
| | + | </syntaxhighlight><source lang="bash"> |
| | #!/bin/bash | | #!/bin/bash |
| | user=$(whoami) | | user=$(whoami) |
| Line 156: |
Line 324: |
| | fi | | fi |
| | </source> | | </source> |
| | + | ===Execute localScript on remote server=== |
| | + | <nowiki>ssh [user]@[server] 'bash -s' < [local_script]</nowiki> |
| | + | |
| | + | ===Remove directorys=== |
| | + | <source lang="bash"> |
| | + | #!/bin/sh |
| | + | die () { |
| | + | echo >&2 "$@" |
| | + | exit 1 |
| | + | } |
| | + | |
| | + | [ "$#" -eq 1 ] || die "1 argument required, $# provided" |
| | + | echo $1 | grep -E -q '^[0-9]+$' || die "Numeric argument required, $1 provided" |
| | + | |
| | + | while read dir |
| | + | do |
| | + | [ -d "$dir" ] || die "Directory $dir does not exist" |
| | + | rm -rf "$dir" |
| | + | done <<EOF |
| | + | ~/myfolder1/$1/anotherfolder |
| | + | ~/myfolder2/$1/yetanotherfolder |
| | + | ~/myfolder3/$1/thisisafolder |
| | + | EOF |
| | + | </source><br /> |
| | + | ===Check if variable is set=== |
| | + | if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi |
| | + | ===Check command success=== |
| | + | |
| | + | <source lang="bash">#!/bin/bash |
| | + | ########################################### |
| | + | # Pull latest code & # |
| | + | # Restart application services # |
| | + | ########################################### |
| | + | |
| | + | OK="[\033[01;32m OK \033[01;36m]\033[01;00m" |
| | + | FAIL="[\033[01;33m FAIL \033[01;36m]\033[01;00m" |
| | + | LOG_FILE=/dev/null |
| | + | |
| | + | function check_success { |
| | + | if [ $? -eq 0 ]; then |
| | + | echo -e ${OK} |
| | + | else |
| | + | echo -e ${FAIL} |
| | + | fi |
| | + | } |
| | + | |
| | + | |
| | + | git pull |
| | + | cd /home/cpc/cpc |
| | + | ./post_pull.sh |
| | + | |
| | + | echo -en "\033[01;36m Restarting Gunicorn ... " |
| | + | sudo /usr/sbin/service gunicorn restart &> ${LOG_FILE} |
| | + | check_success |
| | + | |
| | + | echo -en "\033[01;36m Restarting Daphne ... " |
| | + | sudo /usr/sbin/service daphne restart &> ${LOG_FILE} |
| | + | check_success |
| | + | |
| | + | echo -en "\033[01;36m Restarting Celery ... " |
| | + | sudo /usr/sbin/service celery restart &> ${LOG_FILE} |
| | + | check_success |
| | + | |
| | + | echo -en "\033[01;36m Restarting CeleryBeat ... " |
| | + | sudo /usr/sbin/service celerybeat restart &> ${LOG_FILE} |
| | + | check_success |
| | + | </source> |
| | + | |
| | + | ===Ubuntu proxy setup=== |
| | + | <source lang="bash"> |
| | + | #! /bin/bash |
| | + | HTTP_PROXY_HOST=proxy.example.com |
| | + | HTTP_PROXY_PORT=3128 |
| | + | HTTPS_PROXY_HOST=proxy.example.com |
| | + | HTTPS_PROXY_PORT=3128 |
| | + | |
| | + | gsettings set org.gnome.system.proxy mode manual |
| | + | gsettings set org.gnome.system.proxy.http host "$HTTP_PROXY_HOST" |
| | + | gsettings set org.gnome.system.proxy.http port "$HTTP_PROXY_PORT" |
| | + | gsettings set org.gnome.system.proxy.https host "$HTTPS_PROXY_HOST" |
| | + | gsettings set org.gnome.system.proxy.https port "$HTTPS_PROXY_PORT" |
| | + | |
| | + | sudo sed -i.bak '/http[s]::proxy/Id' /etc/apt/apt.conf |
| | + | sudo tee -a /etc/apt/apt.conf <<EOF |
| | + | Acquire::http::proxy "http://$HTTP_PROXY_HOST:$HTTP_PROXY_PORT/"; |
| | + | Acquire::https::proxy "http://$HTTPS_PROXY_HOST:$HTTPS_PROXY_PORT/"; |
| | + | EOF |
| | + | |
| | + | sudo sed -i.bak '/http[s]_proxy/Id' /etc/environment |
| | + | sudo tee -a /etc/environment <<EOF |
| | + | http_proxy="http://$HTTP_PROXY_HOST:$HTTP_PROXY_PORT/" |
| | + | https_proxy="http://$HTTPS_PROXY_HOST:$HTTPS_PROXY_PORT/" |
| | + | EOF |
| | + | </source> |
| | + | |
| | + | ===Git check version=== |
| | + | <source lang="bash">#!/bin/bash |
| | + | |
| | + | function set_upstream() { |
| | + | echo "No upstream found, setting up branch to track " |
| | + | exit |
| | + | } |
| | + | |
| | + | function set_upstream() { |
| | + | echo "No upstream found" |
| | + | } |
| | + | |
| | + | |
| | + | function check_latest_version(){ |
| | + | UPSTREAM=${1:-'@{u}'} |
| | + | |
| | + | if [ -z $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)) ]; then |
| | + | set_upstream |
| | + | fi |
| | + | |
| | + | echo "Upstream: "$UPSTREAM |
| | + | exit |
| | + | # TODO: check if no upstream is configured, ask if should be automatically configured (git branch --set-upstream-to remotes/$TRACK_REPO/$TRACK_BRANCH) |
| | + | # to get the upstream branch: git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD) |
| | + | |
| | + | LOCAL=$(git rev-parse @) |
| | + | REMOTE=$(git rev-parse "$UPSTREAM") |
| | + | BASE=$(git merge-base @ "$UPSTREAM") |
| | + | |
| | + | if [ ${LOCAL} = ${REMOTE} ]; then |
| | + | status="Up-to-date" |
| | + | elif [ ${LOCAL} = ${BASE} ]; then |
| | + | status="Need-to-pull" |
| | + | elif [ ${REMOTE} = ${BASE} ]; then |
| | + | status="Need-to-push" |
| | + | else |
| | + | status="Diverged" |
| | + | fi |
| | + | } |
| | + | check_latest_version</source> |
| | + | ===Git check for updates and prompt to update=== |
| | + | <source lang="bash"> |
| | + | #!/bin/bash |
| | + | PROJECT_DIR="$HOME/cpc" |
| | + | PROJECT_PYTHON_INTERPRETER="$HOME/Virtualenvs/cpc/bin/python" |
| | + | TRACK_BRANCH="MacBookPablo" |
| | + | TRACK_REPO="origin" |
| | + | |
| | + | |
| | + | cd $PROJECT_DIR |
| | + | remote_commit=$(git branch -av | sed s/*/' '/g | grep $TRACK_BRANCH | grep $TRACK_REPO | awk '{print $2}') |
| | + | echo "Remote commit: $remote_commit" |
| | + | local_commit=$(git branch -av | sed s/*/' '/g | grep $TRACK_BRANCH | grep -v remotes/ | awk '{print $2}') |
| | + | echo "Local commit: $local_commit" |
| | + | |
| | + | |
| | + | django_migrate() { |
| | + | $PROJECT_PYTHON_INTERPRETER manage.py migrate |
| | + | } |
| | + | |
| | + | update() { |
| | + | echo "Updating code" |
| | + | git pull $TRACK_REPO, $TRACK_BRANCH |
| | + | django_migrate |
| | + | } |
| | + | |
| | + | |
| | + | if [ "$remote_commit" = "$local_commit" ]; then |
| | + | echo "Runing latest version" |
| | + | else |
| | + | while true; do |
| | + | read -p "Update available. Do you wish to update? " yn |
| | + | case $yn in |
| | + | [YySs]*) update; break;; |
| | + | [Nn]* ) echo "Skipping update..." ; break;; |
| | + | * ) echo "Choose y/n";; |
| | + | esac |
| | + | done |
| | + | fi |
| | + | |
| | + | </source> |
| | + | |
| | + | ===Logging=== |
| | + | |
| | + | |
| | + | For logging, you can wrap sections of your script in curly braces and redirect the stdout to a log file: |
| | + | <source lang="bash"> |
| | + | { |
| | + | script_command_1 |
| | + | script_command_2 |
| | + | script_command_3 |
| | + | } >> /path/to/log_file |
| | + | </source> |
| | + | |
| | + | ===Links=== |
| | + | [http://tldp.org/LDP/abs/html/ Advanced Bash-Scripting Guide] |