Created
March 3, 2019 06:37
-
-
Save janaz/c4bd909651e6da3a5d1ab16a67c0517c to your computer and use it in GitHub Desktop.
Daemons in Bash
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
SLEEP=0.005 | |
COLS=$(tput cols) | |
ROWS=$(tput lines) | |
RED="\033[0;31m" | |
YELLOW="\033[0;33m" | |
GREEN="\033[0;32m" | |
BLUE="\033[0;34m" | |
CYAN="\033[1;36m" | |
MY_BLUE="\033[1;34m" | |
LIGHT_RED="\033[1;31m" | |
LIGHT_GREEN="\033[1;32m" | |
WHITE="\033[1;37m" | |
LIGHT_GRAY="\033[0;36m" | |
MY_RED="\033[0;31m" | |
COLOR_NONE="\e[0m" | |
function center_one() { | |
local foo="$1" | |
for (( i=0; i<$((($COLS - ${#foo}) / 2)); i++)); do | |
printf " " | |
done | |
write_one "$foo" | |
} | |
function write_one() { | |
local foo="$1" | |
for (( i=0; i<${#foo}; i++ )); do | |
if [ "${foo:$i:1}" == "%" ]; then | |
printf "%%" | |
else | |
printf "${foo:$i:1}" | |
fi | |
if [ "${foo:$i:1}" != " " ]; then | |
sleep $SLEEP | |
fi | |
done | |
echo | |
} | |
function center() { | |
echo "$1" |while read l; do | |
center_one "$l" | |
done | |
} | |
function write() { | |
echo "$1" |while read l; do | |
write_one "$l" | |
done | |
} | |
function wait_key_press() { | |
read -n1 -s x | |
if [ "$x" == "p" -o "$x" == "P" -o "$x" == "[" -o "$x" == "{" -o "$x" == "," -o "$x" == "<" ]; then | |
echo "P" | |
else | |
echo "N" | |
fi | |
} | |
function finish_page() { | |
local cur_row=$1 | |
while [ "$cur_row" -lt "$ROWS" ]; do | |
echo | |
sleep $SLEEP | |
cur_row=$(($cur_row + 1)) | |
done | |
} | |
function breaks() { | |
local cur_row=0 | |
while [ "$cur_row" -lt "$1" ]; do | |
echo | |
sleep $SLEEP | |
cur_row=$(($cur_row + 1)) | |
done | |
} | |
function page_1() { | |
write_one | |
center "D A E M O N S I N B A S H" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 6 | |
center "Tomasz Janowski" | |
finish_page 11 | |
n=$(wait_key_press) | |
} | |
function page_1a { | |
write_one | |
center "BASH" | |
center "‾‾‾‾" | |
breaks 5 | |
write_one " Bash is a command processor that typically runs in a text" | |
write_one " window, where the user types commands that cause actions." | |
write_one | |
write_one " Bash can also read commands from a file, called a script." | |
write_one " Like all Unix shells, it supports filename wildcarding," | |
write_one " piping, here documents, command substitution, variables" | |
write_one " and control structures for condition-testing and iteration." | |
breaks 3 | |
printf "${BLUE}" | |
center_one "http://en.wikipedia.org/wiki/Bash_(Unix_shell)" | |
printf "$COLOR_NONE" | |
finish_page 20 | |
n=$(wait_key_press) | |
} | |
function page_2() { | |
write_one | |
center "PRESENTATIONS IN BASH" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 6 | |
write_one " ★ Presentation as a code" | |
write_one " ★ High contrast" | |
printf " ★ ${RED}C${CYAN}O${YELLOW}L${BLUE}O${GREEN}R${MY_RED}S ${YELLOW}! ${COLOR_NONE}" | |
write_one " ---- but they're hard ◕︵◕" | |
write_one " ★ No transitions" | |
write_one " ★ Unicode emoji \( ゚◡゚)/" | |
write_one " ★ Can be dockerized" | |
finish_page 16 | |
n=$(wait_key_press) | |
} | |
function page_3() { | |
write_one | |
center "BACK TO DAEMONS" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 5 | |
write_one " In multitasking computer operating systems," | |
write_one " a daemon (/ˈdiːmən/ or /ˈdeɪmən/) is a computer" | |
write_one " program that runs as a background process," | |
write_one " rather than being under the direct control of" | |
write_one " an interactive user." | |
breaks 3 | |
printf "${BLUE}" | |
center_one "http://en.wikipedia.org/wiki/Daemon_(computing)" | |
printf "$COLOR_NONE" | |
finish_page 18 | |
n=$(wait_key_press) | |
} | |
function page_4() { | |
write_one | |
center "BACK TO DAEMONS" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 3 | |
write_one " Daemon lifecycle" | |
write_one "" | |
write_one " PARENT PROCESS" | |
write_one " |" | |
write_one " (dissociate from TTY)" | |
write_one " |" | |
write_one " |" | |
write_one " +---- FORK (continues running in detached mode)" | |
write_one " |" | |
write_one " |" | |
write_one " (parent exits)" | |
breaks 1 | |
finish_page 19 | |
n=$(wait_key_press) | |
} | |
function page_4a() { | |
write_one | |
center "WHY BASH? (yಠ,ಠ)y" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 3 | |
write_one " ★ We had a problem to solve: Make the most recent locations data" | |
write_one " always available on the filesystem for apps to consume" | |
write_one " 1. Check if a new locations data package is available" | |
write_one " 2. Download and unpack the new package" | |
write_one " 3. Repeat" | |
write_one | |
write_one " ★ We have to provide the locations data to a huge number of REA apps" | |
write_one " which are deployed to many different environments" | |
finish_page 15 | |
n=$(wait_key_press) | |
} | |
function page_4b() { | |
write_one | |
center "WHY BASH? (yಠ,ಠ)y" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 3 | |
write_one " ★ Minimum set of dependencies (Only standard Linux packages)" | |
write_one " ★ Rock solid technology (Bash + Curl + Tar + Openssl)" | |
write_one " ★ No compilation, language runtime, package managers, libraries" | |
write_one " ★ Will run everywhere: Cloud, Data Centre (even on Lenny), Docker" | |
write_one | |
write_one " ★ Not recommended for anything more complex" | |
finish_page 13 | |
n=$(wait_key_press) | |
} | |
function page_5() { | |
write_one | |
center "DETACH IN BASH" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 3 | |
write_one "$ cat run-detach.sh" | |
write_one "" | |
write_one "nohup \\ # detach from TTY" | |
write_one " run.sh \\ # the main script (daemon)" | |
write_one " 0<&- \\ # close STDIN" | |
write_one " 2>err.log \\ # redirect STDERR" | |
write_one " >app.log \\ # redirect STDOUT" | |
write_one " & # run in a subshell (fork)" | |
write_one | |
write_one "echo \$! > app.pid # store the PID of the main script" | |
write_one | |
write_one "exit 0 # the parent script exits here" | |
finish_page 19 | |
n=$(wait_key_press) | |
} | |
function page_6() { | |
write_one | |
center "KILLING THE DAEMON" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 3 | |
write_one " # /etc/init.d/my_daemon stop" | |
write_one " sends SIGTERM signal to our main script" | |
write_one | |
write_one " it's the same as killing the process manually:" | |
write_one " \$ ps ax" | |
write_one " 3 s007 S 0:04.13 ./run.sh" | |
write_one | |
write_one " \$ kill 3" | |
write_one | |
write_one " Will our script cleanly exit?" | |
finish_page 17 | |
n=$(wait_key_press) | |
} | |
function page_7() { | |
write_one | |
center "KILLING THE DAEMON" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 2 | |
write_one " \$ cat run.sh" | |
write_one " #!/bin/bash" | |
write_one " while true; do" | |
write_one " echo still alive" | |
write_one " long_running_task" | |
write_one " done" | |
write_one | |
write_one " \$ /etc/init.d/my_daemon stop" | |
write_one | |
write_one " \$ ps ax" | |
write_one " 3 s007 S 0:04.13 long_running_task" | |
write_one | |
write_one " ★ The TERM signal is only sent to the main script" | |
write_one " ★ All child processes will continue running" | |
finish_page 20 | |
n=$(wait_key_press) | |
} | |
function page_8() { | |
write_one | |
center "KILLING THE DAEMON AND ALL CHILD PROCESSES" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 2 | |
write_one " \$ cat run.sh" | |
write_one " #!/bin/bash" | |
write_one " trap shutdown SIGTERM" | |
write_one | |
write_one " function shutdown() {" | |
write_one " pgid=\$(ps -o pgid= \$\$ | grep -o [0-9]*) # Get our process group id" | |
write_one " setsid kill -- -\$pgid # Kill all processes from the process group" | |
write_one " # \`setdid\` ensures that the kill will be" | |
write_one " # executed by the process group leaders" | |
write_one " exit 0" | |
write_one " }" | |
write_one | |
write_one " ★ All Bash child processes belong to the same process group" | |
write_one " ★ It is possible to kill all processes with a given process group id" | |
finish_page 22 | |
n=$(wait_key_press) | |
} | |
function page_9() { | |
write_one | |
center "SENDING SIGINT TO THE DAEMON" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 3 | |
write_one " $ cat run.sh" | |
write_one " #!/bin/bash" | |
write_one " while true; do" | |
write_one " echo still alive" | |
write_one " sleep 3600" | |
write_one " done" | |
write_one | |
write_one " $ kill -INT <pid> # it's like Ctrl+C" | |
write_one | |
write_one " ★ Bash doesn't process SIGINT during sleep" | |
write_one " ★ the daemon will still be running for about 1 hour" | |
finish_page 18 | |
n=$(wait_key_press) | |
} | |
function page_10() { | |
write_one | |
center "SENDING SIGINT TO THE DAEMON" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 3 | |
write_one " $ cat run.sh" | |
write_one " #!/bin/bash" | |
write_one | |
write_one " while true; do" | |
write_one " echo still alive" | |
write_one " sleep 3600 & # execute sleep in a subprocess" | |
write_one " wait \$! # wait for the subprocess to finish" | |
write_one " done" | |
finish_page 15 | |
n=$(wait_key_press) | |
} | |
function page_11() { | |
write_one | |
center "LOGGING FROM THE DAEMON" | |
center "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" | |
breaks 1 | |
write_one " $ cat run.sh" | |
write_one " #!/bin/bash" | |
write_one | |
write_one " function log() {" | |
write_one ' echo -e "[$(date +"%d/%b/%Y:%H:%M:%S %z")]\t$(hostname -f)\t$*"' | |
write_one " }" | |
write_one ' log "hello"' | |
write_one | |
write_one " $ cat application.log" | |
write_one ' [05/May/2015:00:09:54 +1000] VIC009235M.lan hello' | |
write_one | |
write_one | |
write_one " ★ Use standard format (i.e. Apache)" | |
write_one " ★ Include timestamp (UTC or with TZ info)" | |
finish_page 19 | |
n=$(wait_key_press) | |
} | |
function page_last() { | |
write "" | |
breaks 8 | |
center '¯\\_(ツ)_/¯' | |
breaks 4 | |
center 'THE END' | |
breaks 3 | |
finish_page 19 | |
n=$(wait_key_press) | |
} | |
page_1 | |
page_2 | |
page_1a | |
page_3 | |
page_4 | |
page_4a | |
page_4b | |
page_5 | |
page_6 | |
page_7 | |
page_8 | |
page_9 | |
page_10 | |
page_11 | |
page_last |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment