From 58fa7533b1d3e744a8f56ad1de631e986ee32626 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 10 Dec 2023 07:56:23 +0200 Subject: Update content for md --- gemfeed/2021-04-24-welcome-to-the-geminispace.md | 4 +- gemfeed/2022-01-01-bash-golf-part-2.md | 2 + index.md | 2 +- uptime-stats.md | 138 +++++++++++------------ 4 files changed, 74 insertions(+), 72 deletions(-) diff --git a/gemfeed/2021-04-24-welcome-to-the-geminispace.md b/gemfeed/2021-04-24-welcome-to-the-geminispace.md index 682d5f47..fc9e43e9 100644 --- a/gemfeed/2021-04-24-welcome-to-the-geminispace.md +++ b/gemfeed/2021-04-24-welcome-to-the-geminispace.md @@ -75,8 +75,8 @@ This site was generated with Gemtexter. You can read more about it here: Check out one of the following links for more information about Gemini. For example, you will find a FAQ that explains why the protocol is named Gemini. Many Gemini capsules are dual-hosted via Gemini and HTTP(S) so that people new to Gemini can sneak peek at the content with a regular web browser. Some people go as far as tri-hosting all their content via HTTP(S), Gemini and Gopher. -[gemini://gemini.circumlunar.space](gemini://gemini.circumlunar.space) -[https://gemini.circumlunar.space](https://gemini.circumlunar.space) +[gemini://geminiprotocol.net/](gemini://geminiprotocol.net/) +[https://geminiprotocol.net/](https://geminiprotocol.net/) Other related posts are: diff --git a/gemfeed/2022-01-01-bash-golf-part-2.md b/gemfeed/2022-01-01-bash-golf-part-2.md index f9792a39..21bd47f9 100644 --- a/gemfeed/2022-01-01-bash-golf-part-2.md +++ b/gemfeed/2022-01-01-bash-golf-part-2.md @@ -47,6 +47,8 @@ Foo Foo ``` +> Update: A reader pointed out, that the redirection should actually go to `/proc/self/fd/1` and not `0`. But apparently, either way works for this particular example. Do you know why? + Other useful redirections are: * Redirect stderr to stdin: "echo foo 2>&1" diff --git a/index.md b/index.md index 93d01508..aa2c6103 100644 --- a/index.md +++ b/index.md @@ -1,6 +1,6 @@ # foo.zone -> This site was generated at 2023-11-11T22:22:24+02:00 by `Gemtexter` +> This site was generated at 2023-12-10T07:56:06+02:00 by `Gemtexter` ``` |\---/| diff --git a/uptime-stats.md b/uptime-stats.md index 369785ee..3c476c6d 100644 --- a/uptime-stats.md +++ b/uptime-stats.md @@ -1,6 +1,6 @@ # My machine uptime stats -> This site was last updated at 2023-11-11T22:22:24+02:00 +> This site was last updated at 2023-12-10T07:56:06+02:00 The following stats were collected via `uptimed` on all of my personal computers over many years and the output was generated by `guprecords`, the global uptime records stats analyser of mine. @@ -27,20 +27,20 @@ Boots is the total number of host boots over the entire lifespan. | 4. | callisto | 153 | | 5. | dionysus | 136 | | 6. | tauceti-e | 120 | -| 7. | *earth | 107 | +| 7. | *earth | 113 | | 8. | pluto | 51 | -| 9. | *mega15289 | 50 | -| 10. | makemake | 50 | +| 9. | makemake | 50 | +| 10. | *mega15289 | 50 | | 11. | *t450 | 45 | | 12. | phobos | 40 | | 13. | mega8477 | 40 | | 14. | sun | 33 | -| 15. | vulcan | 19 | -| 16. | *blowfish | 19 | +| 15. | *blowfish | 19 | +| 16. | vulcan | 19 | | 17. | tauceti | 16 | | 18. | sagittarius | 15 | | 19. | deltavega | 12 | -| 20. | *fishfinger | 11 | +| 20. | *fishfinger | 12 | +-----+----------------+-------+ ``` @@ -59,15 +59,15 @@ Uptime is the total uptime of a host over the entire lifespan. | 5. | deltavega | 3 years, 1 months, 21 days | | 6. | pluto | 2 years, 10 months, 29 days | | 7. | tauceti | 2 years, 3 months, 19 days | -| 8. | *mega15289 | 1 years, 10 months, 14 days | -| 9. | tauceti-f | 1 years, 9 months, 18 days | -| 10. | *earth | 1 years, 9 months, 16 days | -| 11. | *blowfish | 1 years, 9 months, 6 days | +| 8. | *earth | 1 years, 11 months, 26 days | +| 9. | *blowfish | 1 years, 11 months, 22 days | +| 10. | *mega15289 | 1 years, 11 months, 12 days | +| 11. | tauceti-f | 1 years, 9 months, 18 days | | 12. | mega8477 | 1 years, 3 months, 25 days | -| 13. | host0 | 1 years, 3 months, 9 days | -| 14. | tauceti-e | 1 years, 2 months, 20 days | -| 15. | makemake | 1 years, 1 months, 25 days | -| 16. | *fishfinger | 1 years, 1 months, 3 days | +| 13. | *fishfinger | 1 years, 3 months, 21 days | +| 14. | host0 | 1 years, 3 months, 9 days | +| 15. | tauceti-e | 1 years, 2 months, 20 days | +| 16. | makemake | 1 years, 1 months, 25 days | | 17. | callisto | 0 years, 10 months, 31 days | | 18. | alphacentauri | 0 years, 10 months, 28 days | | 19. | london | 0 years, 9 months, 16 days | @@ -92,16 +92,16 @@ Score is calculated by combining all other metrics. | 7. | pluto | 182 | | 8. | dionysus | 156 | | 9. | tauceti | 141 | -| 10. | *mega15289 | 130 | -| 11. | *earth | 125 | -| 12. | *blowfish | 110 | +| 10. | *earth | 138 | +| 11. | *mega15289 | 137 | +| 12. | *blowfish | 123 | | 13. | tauceti-f | 108 | | 14. | tauceti-e | 96 | | 15. | makemake | 90 | | 16. | callisto | 86 | -| 17. | mega8477 | 80 | -| 18. | host0 | 76 | -| 19. | *fishfinger | 67 | +| 17. | *fishfinger | 80 | +| 18. | mega8477 | 80 | +| 19. | host0 | 76 | | 20. | mars | 67 | +-----+----------------+-------+ ``` @@ -121,7 +121,7 @@ Downtime is the total downtime of a host over the entire lifespan. | 5. | makemake | 1 years, 3 months, 26 days | | 6. | mars | 1 years, 2 months, 10 days | | 7. | tauceti-e | 0 years, 12 months, 9 days | -| 8. | *mega15289 | 0 years, 9 months, 23 days | +| 8. | *mega15289 | 0 years, 11 months, 2 days | | 9. | *t450 | 0 years, 9 months, 17 days | | 10. | sirius | 0 years, 8 months, 20 days | | 11. | *earth | 0 years, 5 months, 24 days | @@ -153,18 +153,18 @@ Lifespan is the total uptime + the total downtime of a host. | 6. | uugrn | 3 years, 5 months, 5 days | | 7. | deltavega | 3 years, 1 months, 21 days | | 8. | pluto | 2 years, 10 months, 30 days | -| 9. | *mega15289 | 2 years, 7 months, 5 days | +| 9. | *mega15289 | 2 years, 9 months, 13 days | | 10. | makemake | 2 years, 4 months, 19 days | -| 11. | tauceti | 2 years, 3 months, 22 days | -| 12. | callisto | 2 years, 3 months, 13 days | -| 13. | *earth | 2 years, 2 months, 7 days | +| 11. | *earth | 2 years, 4 months, 18 days | +| 12. | tauceti | 2 years, 3 months, 22 days | +| 13. | callisto | 2 years, 3 months, 13 days | | 14. | tauceti-e | 2 years, 1 months, 29 days | -| 15. | tauceti-f | 1 years, 9 months, 20 days | -| 16. | *blowfish | 1 years, 9 months, 7 days | +| 15. | *blowfish | 1 years, 11 months, 23 days | +| 16. | tauceti-f | 1 years, 9 months, 20 days | | 17. | mars | 1 years, 8 months, 19 days | | 18. | host0 | 1 years, 4 months, 10 days | | 19. | mega8477 | 1 years, 4 months, 1 days | -| 20. | sirius | 1 years, 2 months, 24 days | +| 20. | *fishfinger | 1 years, 3 months, 21 days | +-----+----------------+-----------------------------+ ``` @@ -178,23 +178,23 @@ Boots is the total number of host boots over the entire lifespan. +-----+----------------+-------+ | 1. | FreeBSD 10... | 551 | | 2. | Linux 3... | 550 | -| 3. | *Linux 5... | 249 | +| 3. | *Linux 5... | 250 | | 4. | Linux 4... | 164 | | 5. | FreeBSD 11... | 153 | | 6. | *FreeBSD 13... | 143 | -| 7. | *Linux 6... | 51 | -| 8. | Darwin 13... | 40 | -| 9. | *OpenBSD 7... | 40 | +| 7. | *Linux 6... | 57 | +| 8. | *OpenBSD 7... | 41 | +| 9. | Darwin 13... | 40 | | 10. | FreeBSD 5... | 25 | | 11. | Linux 2... | 22 | | 12. | Darwin 21... | 18 | | 13. | Darwin 15... | 15 | -| 14. | Darwin 18... | 13 | -| 15. | *Darwin 22... | 12 | -| 16. | FreeBSD 7... | 10 | -| 17. | FreeBSD 6... | 10 | -| 18. | OpenBSD 4... | 10 | -| 19. | Darwin 20... | 6 | +| 14. | *Darwin 22... | 14 | +| 15. | Darwin 18... | 12 | +| 16. | FreeBSD 6... | 10 | +| 17. | OpenBSD 4... | 10 | +| 18. | FreeBSD 7... | 10 | +| 19. | Darwin 20... | 5 | | 20. | Darwin 19... | 1 | +-----+----------------+-------+ ``` @@ -209,22 +209,22 @@ Uptime is the total uptime of a host over the entire lifespan. +-----+----------------+------------------------------+ | 1. | Linux 3... | 15 years, 10 months, 25 days | | 2. | FreeBSD 10... | 5 years, 9 months, 9 days | -| 3. | *Linux 5... | 4 years, 4 months, 28 days | -| 4. | *OpenBSD 7... | 3 years, 5 months, 8 days | +| 3. | *Linux 5... | 4 years, 7 months, 14 days | +| 4. | *OpenBSD 7... | 3 years, 10 months, 9 days | | 5. | Linux 4... | 2 years, 8 months, 9 days | | 6. | FreeBSD 11... | 2 years, 4 months, 28 days | | 7. | Linux 2... | 1 years, 11 months, 21 days | | 8. | Darwin 13... | 1 years, 3 months, 25 days | | 9. | FreeBSD 6... | 1 years, 3 months, 9 days | -| 10. | *Linux 6... | 0 years, 10 months, 31 days | +| 10. | *Linux 6... | 1 years, 1 months, 10 days | | 11. | OpenBSD 4... | 0 years, 8 months, 12 days | | 12. | Darwin 21... | 0 years, 8 months, 9 days | -| 13. | Darwin 18... | 0 years, 7 months, 18 days | -| 14. | Darwin 15... | 0 years, 6 months, 15 days | -| 15. | *Darwin 22... | 0 years, 5 months, 25 days | +| 13. | Darwin 18... | 0 years, 7 months, 12 days | +| 14. | *Darwin 22... | 0 years, 7 months, 6 days | +| 15. | Darwin 15... | 0 years, 6 months, 15 days | | 16. | FreeBSD 5... | 0 years, 5 months, 18 days | | 17. | *FreeBSD 13... | 0 years, 4 months, 7 days | -| 18. | Darwin 20... | 0 years, 3 months, 21 days | +| 18. | Darwin 20... | 0 years, 3 months, 14 days | | 19. | FreeBSD 7... | 0 years, 2 months, 5 days | | 20. | Darwin 19... | 0 years, 1 months, 9 days | +-----+----------------+------------------------------+ @@ -240,22 +240,22 @@ Score is calculated by combining all other metrics. +-----+----------------+-------+ | 1. | Linux 3... | 1045 | | 2. | FreeBSD 10... | 406 | -| 3. | *Linux 5... | 296 | -| 4. | *OpenBSD 7... | 217 | +| 3. | *Linux 5... | 310 | +| 4. | *OpenBSD 7... | 244 | | 5. | Linux 4... | 178 | | 6. | FreeBSD 11... | 159 | | 7. | Linux 2... | 121 | | 8. | Darwin 13... | 80 | | 9. | FreeBSD 6... | 75 | -| 10. | *Linux 6... | 59 | -| 11. | Darwin 21... | 39 | -| 12. | OpenBSD 4... | 39 | -| 13. | Darwin 18... | 35 | -| 14. | *FreeBSD 13... | 31 | -| 15. | Darwin 15... | 29 | -| 16. | *Darwin 22... | 28 | +| 10. | *Linux 6... | 72 | +| 11. | OpenBSD 4... | 39 | +| 12. | Darwin 21... | 39 | +| 13. | *Darwin 22... | 36 | +| 14. | Darwin 18... | 34 | +| 15. | *FreeBSD 13... | 31 | +| 16. | Darwin 15... | 29 | | 17. | FreeBSD 5... | 25 | -| 18. | Darwin 20... | 14 | +| 18. | Darwin 20... | 13 | | 19. | FreeBSD 7... | 7 | | 20. | Darwin 19... | 1 | +-----+----------------+-------+ @@ -269,10 +269,10 @@ Boots is the total number of host boots over the entire lifespan. +-----+------------+-------+ | Pos | KernelName | Boots | +-----+------------+-------+ -| 1. | *Linux | 1036 | +| 1. | *Linux | 1043 | | 2. | *FreeBSD | 892 | | 3. | *Darwin | 105 | -| 4. | *OpenBSD | 50 | +| 4. | *OpenBSD | 51 | +-----+------------+-------+ ``` @@ -281,14 +281,14 @@ Boots is the total number of host boots over the entire lifespan. Uptime is the total uptime of a host over the entire lifespan. ``` -+-----+------------+-----------------------------+ -| Pos | KernelName | Uptime | -+-----+------------+-----------------------------+ -| 1. | *Linux | 25 years, 6 months, 18 days | -| 2. | *FreeBSD | 9 years, 12 months, 8 days | -| 3. | *OpenBSD | 3 years, 12 months, 17 days | -| 4. | *Darwin | 3 years, 6 months, 19 days | -+-----+------------+-----------------------------+ ++-----+------------+------------------------------+ +| Pos | KernelName | Uptime | ++-----+------------+------------------------------+ +| 1. | *Linux | 25 years, 11 months, 12 days | +| 2. | *FreeBSD | 9 years, 12 months, 8 days | +| 3. | *OpenBSD | 4 years, 5 months, 20 days | +| 4. | *Darwin | 3 years, 7 months, 18 days | ++-----+------------+------------------------------+ ``` ## Top 20 Score's by KernelName @@ -299,10 +299,10 @@ Score is calculated by combining all other metrics. +-----+------------+-------+ | Pos | KernelName | Score | +-----+------------+-------+ -| 1. | *Linux | 1699 | +| 1. | *Linux | 1725 | | 2. | *FreeBSD | 706 | -| 3. | *OpenBSD | 256 | -| 4. | *Darwin | 230 | +| 3. | *OpenBSD | 283 | +| 4. | *Darwin | 235 | +-----+------------+-------+ ``` -- cgit v1.2.3 From 554facb80137bed60ef0f4b4a2606d5c96b33eb0 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 10 Dec 2023 11:38:30 +0200 Subject: Update content for md --- .../2021-05-16-personal-bash-coding-style-guide.md | 1 + ...-05-gemtexter-one-bash-script-to-rule-it-all.md | 1 + gemfeed/2021-11-29-bash-golf-part-1.md | 2 + gemfeed/2022-01-01-bash-golf-part-2.md | 2 + ...s-static-web-photo-albums-with-photoalbum.sh.md | 1 + gemfeed/2023-12-10-bash-golf-part-3.md | 369 +++++++++++++++++++++ .../2023-12-10-bash-golf-part-3/bash-fork-bomb.jpg | Bin 0 -> 209399 bytes gemfeed/index.md | 1 + index.md | 3 +- uptime-stats.md | 2 +- 10 files changed, 380 insertions(+), 2 deletions(-) create mode 100644 gemfeed/2023-12-10-bash-golf-part-3.md create mode 100644 gemfeed/2023-12-10-bash-golf-part-3/bash-fork-bomb.jpg diff --git a/gemfeed/2021-05-16-personal-bash-coding-style-guide.md b/gemfeed/2021-05-16-personal-bash-coding-style-guide.md index 21cd38f2..8eebbbe0 100644 --- a/gemfeed/2021-05-16-personal-bash-coding-style-guide.md +++ b/gemfeed/2021-05-16-personal-bash-coding-style-guide.md @@ -386,6 +386,7 @@ Other related posts are: [2021-06-05 Gemtexter - One Bash script to rule it all](./2021-06-05-gemtexter-one-bash-script-to-rule-it-all.md) [2021-11-29 Bash Golf Part 1](./2021-11-29-bash-golf-part-1.md) [2022-01-01 Bash Golf Part 2](./2022-01-01-bash-golf-part-2.md) +[2023-12-10 Bash Golf Part 3](./2023-12-10-bash-golf-part-3.md) E-Mail your comments to `paul@nospam.buetow.org` :-) diff --git a/gemfeed/2021-06-05-gemtexter-one-bash-script-to-rule-it-all.md b/gemfeed/2021-06-05-gemtexter-one-bash-script-to-rule-it-all.md index de6a843f..bf69af53 100644 --- a/gemfeed/2021-06-05-gemtexter-one-bash-script-to-rule-it-all.md +++ b/gemfeed/2021-06-05-gemtexter-one-bash-script-to-rule-it-all.md @@ -173,6 +173,7 @@ Other related posts are: [2022-08-27 Gemtexter 1.1.0 - Let's Gemtext again](./2022-08-27-gemtexter-1.1.0-lets-gemtext-again.md) [2023-03-25 Gemtexter 2.0.0 - Let's Gemtext again²](./2023-03-25-gemtexter-2.0.0-lets-gemtext-again-2.md) [2023-07-21 Gemtexter 2.1.0 - Let's Gemtext again³](./2023-07-21-gemtexter-2.1.0-lets-gemtext-again-3.md) +[2023-12-10 Bash Golf Part 3](./2023-12-10-bash-golf-part-3.md) E-Mail your comments to `paul@nospam.buetow.org` :-) diff --git a/gemfeed/2021-11-29-bash-golf-part-1.md b/gemfeed/2021-11-29-bash-golf-part-1.md index 60c4ed08..63ffebb0 100644 --- a/gemfeed/2021-11-29-bash-golf-part-1.md +++ b/gemfeed/2021-11-29-bash-golf-part-1.md @@ -18,6 +18,7 @@ This is the first blog post about my Bash Golf series. This series is about rand [2021-11-29 Bash Golf Part 1 (You are currently reading this)](./2021-11-29-bash-golf-part-1.md) [2022-01-01 Bash Golf Part 2](./2022-01-01-bash-golf-part-2.md) +[2023-12-10 Bash Golf Part 3](./2023-12-10-bash-golf-part-3.md) ## TCP/IP networking @@ -469,6 +470,7 @@ Other related posts are: [2021-06-05 Gemtexter - One Bash script to rule it all](./2021-06-05-gemtexter-one-bash-script-to-rule-it-all.md) [2021-11-29 Bash Golf Part 1 (You are currently reading this)](./2021-11-29-bash-golf-part-1.md) [2022-01-01 Bash Golf Part 2](./2022-01-01-bash-golf-part-2.md) +[2023-12-10 Bash Golf Part 3](./2023-12-10-bash-golf-part-3.md) E-Mail your comments to `paul@nospam.buetow.org` :-) diff --git a/gemfeed/2022-01-01-bash-golf-part-2.md b/gemfeed/2022-01-01-bash-golf-part-2.md index 21bd47f9..88a17126 100644 --- a/gemfeed/2022-01-01-bash-golf-part-2.md +++ b/gemfeed/2022-01-01-bash-golf-part-2.md @@ -18,6 +18,7 @@ This is the second blog post about my Bash Golf series. This series is random Ba [2021-11-29 Bash Golf Part 1](./2021-11-29-bash-golf-part-1.md) [2022-01-01 Bash Golf Part 2 (You are currently reading this)](./2022-01-01-bash-golf-part-2.md) +[2023-12-10 Bash Golf Part 3](./2023-12-10-bash-golf-part-3.md) ## Redirection @@ -488,6 +489,7 @@ Other related posts are: [2021-06-05 Gemtexter - One Bash script to rule it all](./2021-06-05-gemtexter-one-bash-script-to-rule-it-all.md) [2021-11-29 Bash Golf Part 1](./2021-11-29-bash-golf-part-1.md) [2022-01-01 Bash Golf Part 2 (You are currently reading this)](./2022-01-01-bash-golf-part-2.md) +[2023-12-10 Bash Golf Part 3](./2023-12-10-bash-golf-part-3.md) E-Mail your comments to `paul@nospam.buetow.org` :-) diff --git a/gemfeed/2023-10-29-kiss-static-web-photo-albums-with-photoalbum.sh.md b/gemfeed/2023-10-29-kiss-static-web-photo-albums-with-photoalbum.sh.md index 1b3639e7..140c9925 100644 --- a/gemfeed/2023-10-29-kiss-static-web-photo-albums-with-photoalbum.sh.md +++ b/gemfeed/2023-10-29-kiss-static-web-photo-albums-with-photoalbum.sh.md @@ -268,6 +268,7 @@ Other Bash and KISS-related posts are: [2022-01-01 Bash Golf Part 2](./2022-01-01-bash-golf-part-2.md) [2023-06-01 KISS server monitoring with Gogios](./2023-06-01-kiss-server-monitoring-with-gogios.md) [2023-10-29 KISS static web photo albums with `photoalbum.sh` (You are currently reading this)](./2023-10-29-kiss-static-web-photo-albums-with-photoalbum.sh.md) +[2023-12-10 Bash Golf Part 3](./2023-12-10-bash-golf-part-3.md) E-Mail your comments to `paul@nospam.buetow.org` :-) diff --git a/gemfeed/2023-12-10-bash-golf-part-3.md b/gemfeed/2023-12-10-bash-golf-part-3.md new file mode 100644 index 00000000..46cd231f --- /dev/null +++ b/gemfeed/2023-12-10-bash-golf-part-3.md @@ -0,0 +1,369 @@ +# Bash Golf Part 3 + +> Published at 2023-12-10T11:35:54+02:00 + +``` + + '\ '\ '\ . . |>18>> + \ \ \ . ' . | + O>> O>> O>> . 'o | + \ .\. .. .\. .. . | + /\ . /\ . /\ . . | + / / . / / .'. / / .' . | +jgs^^^^^^^`^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Art by Joan Stark, mod. by Paul Buetow +``` + +This is the third blog post about my Bash Golf series. This series is random Bash tips, tricks, and weirdnesses I have encountered over time. + +[2021-11-29 Bash Golf Part 1](./2021-11-29-bash-golf-part-1.md) +[2022-01-01 Bash Golf Part 2](./2022-01-01-bash-golf-part-2.md) +[2023-12-10 Bash Golf Part 3 (You are currently reading this)](./2023-12-10-bash-golf-part-3.md) + +## `FUNCNAME` + +`FUNCNAME` is an array you are looking for a way to dynamically determine the name of the current function (which could be considered the callee in the context of its own execution), you can use the special variable `FUNCNAME`. This is an array variable that contains the names of all shell functions currently in the execution call stack. The element `FUNCNAME[0]` holds the name of the currently executing function, `FUNCNAME[1]` the name of the function that called that, and so on. + +This is particularly useful for logging when you want to include the callee function in the log output. E.g. look at this log helper: + +```bash +#!/usr/bin/env bash + +log () { + local -r level="$1"; shift + local -r message="$1"; shift + local -i pid="$$" + + local -r callee=${FUNCNAME[1]} + local -r stamp=$(date +%Y%m%d-%H%M%S) + + echo "$level|$stamp|$pid|$callee|$message" >&2 +} + +at_home_friday_evening () { + log INFO 'One Peperoni Pizza, please' +} + +at_home_friday_evening +``` + +The output is as follows: + +```bash +❯ ./logexample.sh +INFO|20231210-082732|123002|at_home_friday_evening|One Peperoni Pizza, please +``` + +## `:(){ :|:& };:` + +This one may be widely known already, but I am including it here as I found a cute image illustrating it. But to break `:(){ :|:& };:` down: + +* `:(){ }` is really a declaration of the function `:` +* The `;` is ending the current statement +* The `:` at the end is calling the function `:` +* `:|:&` is the function body + +Let's break down the function body `:|:&`: + +* The first `:` is calling the function recursively +* The `|:` is piping the output to the function `:` again (parallel recursion) +* The `&` lets it run in the background. + +So, it's a fork bomb. If you run it, your computer will run out of resources eventually. (Modern Linux distributions could have reasonable limits configured for your login session, so it won't bring down your whole system anymore unless you run it as `root`!) + +And here is the cute illustration: + +[![Bash fork bomb](./2023-12-10-bash-golf-part-3/bash-fork-bomb.jpg "Bash fork bomb")](./2023-12-10-bash-golf-part-3/bash-fork-bomb.jpg) + +## Inner functions + +Bash defines variables as it is interpreting the code. The same applies to function declarations. Let's consider this code: + +```bash +#!/usr/bin/env bash + +outer() { + inner() { + echo 'Intel inside!' + } + inner +} + +inner +outer +inner +``` + +And let's execute it: + +``` +❯ ./inner.sh +/tmp/inner.sh: line 10: inner: command not found +Intel inside! +Intel inside! +``` + +What happened? The first time `inner` was called, it wasn't defined yet. That only happens after the `outer` run. Note that `inner` will still be globally defined. But functions can be declared multiple times (the last version wins): + +```bash +#!/usr/bin/env bash + +outer1() { + inner() { + echo 'Intel inside!' + } + inner +} + +outer2() { + inner() { + echo 'Wintel inside!' + } + inner +} + +outer1 +inner +outer2 +inner +``` + +And let's run it: + +``` +❯ ./inner2.sh +Intel inside! +Intel inside! +Wintel inside! +Wintel inside! +``` + +## Exporting functions + +Have you ever wondered how to execute a shell function in parallel through `xargs`? The problem is that this won't work: + +```bash +#!/usr/bin/env bash + +some_expensive_operations() { + echo "Doing expensive operations with '$1' from pid $$" +} + +for i in {0..9}; do echo $i; done \ + | xargs -P10 -I{} bash -c 'some_expensive_operations "{}"' +``` + +We try here to run ten parallel processes; each of them should run the `some_expensive_operations` function with a different argument. The arguments are provided to `xargs` through `STDIN` one per line. When executed, we get this: + +``` +❯ ./xargs.sh +bash: line 1: some_expensive_operations: command not found +bash: line 1: some_expensive_operations: command not found +bash: line 1: some_expensive_operations: command not found +bash: line 1: some_expensive_operations: command not found +bash: line 1: some_expensive_operations: command not found +bash: line 1: some_expensive_operations: command not found +bash: line 1: some_expensive_operations: command not found +bash: line 1: some_expensive_operations: command not found +bash: line 1: some_expensive_operations: command not found +bash: line 1: some_expensive_operations: command not found +``` + +There's an easy solution for this. Just export the function! It will then be magically available in any sub-shell! + +```bash +#!/usr/bin/env bash + +some_expensive_operations() { + echo "Doing expensive operations with '$1' from pid $$" +} +export -f some_expensive_operations + +for i in {0..9}; do echo $i; done \ + | xargs -P10 -I{} bash -c 'some_expensive_operations "{}"' +``` + +When we run this now, we get: + +``` +❯ ./xargs.sh +Doing expensive operations with '0' from pid 132831 +Doing expensive operations with '1' from pid 132832 +Doing expensive operations with '2' from pid 132833 +Doing expensive operations with '3' from pid 132834 +Doing expensive operations with '4' from pid 132835 +Doing expensive operations with '5' from pid 132836 +Doing expensive operations with '6' from pid 132837 +Doing expensive operations with '7' from pid 132838 +Doing expensive operations with '8' from pid 132839 +Doing expensive operations with '9' from pid 132840 +``` + +If `some_expensive_function` would call another function, the other function must also be exported. Otherwise, there will be a runtime error again. E.g., this won't work: + +```bash +#!/usr/bin/env bash + +some_other_function() { + echo "$1" +} + +some_expensive_operations() { + some_other_function "Doing expensive operations with '$1' from pid $$" +} +export -f some_expensive_operations + +for i in {0..9}; do echo $i; done \ + | xargs -P10 -I{} bash -c 'some_expensive_operations "{}"' +``` + +... because `some_other_function` isn't exported! You will also need to add an `export -f some_other_function`! + +## Dynamic variables with `local` + +You may know that `local` is how to declare local variables in a function. Most don't know that those variables actually have dynamic scope. Let's consider the following example: + +```bash +#!/usr/bin/env bash + +foo() { + local foo=bar # Declare local/dynamic variable + bar + echo "$foo" +} + +bar() { + echo "$foo" + foo=baz +} + +foo=foo # Declare global variable +foo # Call function foo +echo "$foo" +``` + +Let's pause a minute. What do you think the output would be? + +Let's run it: + +``` +❯ ./dynamic.sh +bar +baz +foo +``` + +What happened? The variable `foo` (declared with `local`) is available in the function it was declared in and in all other functions down the call stack! We can even modify the value of `foo', and the change will be visible up the call stack. It's not a global variable; on the last line, `echo "$foo"` echoes the global variable content. + + +## `if` conditionals + +Consider all variants here more or less equivalent: + +```bash +#!/usr/bin/env bash + +declare -r foo=foo +declare -r bar=bar + +if [ "$foo" = foo ]; then + if [ "$bar" = bar ]; then + echo ok1 + fi +fi + +if [ "$foo" = foo ] && [ "$bar" == bar ]; then + echo ok2a +fi + +[ "$foo" = foo ] && [ "$bar" == bar ] && echo ok2b + +if [[ "$foo" = foo && "$bar" == bar ]]; then + echo ok3a +fi + + [[ "$foo" = foo && "$bar" == bar ]] && echo ok3b + +if test "$foo" = foo && test "$bar" = bar; then + echo ok4a +fi + +test "$foo" = foo && test "$bar" = bar && echo ok4b +``` + +The output we get is: + +``` +❯ ./if.sh +ok1 +ok2a +ok2b +ok3a +ok3b +ok4a +ok4b +``` + +## Multi-line comments + +You all know how to comment. Put a `#` in front of it. You could use multiple single-line comments or abuse heredocs and redirect it to the `:` no-op command to emulate multi-line comments. + +```bash +#!/usr/bin/env bash + +# Single line comment + +# These are two single line +# comments one after another + +: <> $0 +echo bar +``` + +When it is run, it will do: + +``` +❯ ./if.sh +foo +bar +baz +❯ cat if.sh +#!/usr/bin/env bash + +echo foo +echo echo baz >> $0 +echo bar +echo baz +``` + +So what happened? The `echo baz` line was appended to the script while it was still executed! And the interpreter also picked it up! It tells us that Bash evaluates each line as it encounters it. This can lead to nasty side effects when editing the script while it is still being executed! You should always keep this in mind! + + +Other related posts are: + +[2021-05-16 Personal Bash coding style guide](./2021-05-16-personal-bash-coding-style-guide.md) +[2021-06-05 Gemtexter - One Bash script to rule it all](./2021-06-05-gemtexter-one-bash-script-to-rule-it-all.md) +[2021-11-29 Bash Golf Part 1](./2021-11-29-bash-golf-part-1.md) +[2022-01-01 Bash Golf Part 2](./2022-01-01-bash-golf-part-2.md) +[2023-12-10 Bash Golf Part 3 (You are currently reading this)](./2023-12-10-bash-golf-part-3.md) + +E-Mail your comments to `paul@nospam.buetow.org` :-) + +[Back to the main site](../) diff --git a/gemfeed/2023-12-10-bash-golf-part-3/bash-fork-bomb.jpg b/gemfeed/2023-12-10-bash-golf-part-3/bash-fork-bomb.jpg new file mode 100644 index 00000000..6967c03a Binary files /dev/null and b/gemfeed/2023-12-10-bash-golf-part-3/bash-fork-bomb.jpg differ diff --git a/gemfeed/index.md b/gemfeed/index.md index 5290577c..fcf83d14 100644 --- a/gemfeed/index.md +++ b/gemfeed/index.md @@ -2,6 +2,7 @@ ## To be in the .zone! +[2023-12-10 - Bash Golf Part 3](./2023-12-10-bash-golf-part-3.md) [2023-11-11 - 'Mind Management' book notes](./2023-11-11-mind-management-book-notes.md) [2023-10-29 - KISS static web photo albums with `photoalbum.sh`](./2023-10-29-kiss-static-web-photo-albums-with-photoalbum.sh.md) [2023-09-25 - DTail usage examples](./2023-09-25-dtail-usage-examples.md) diff --git a/index.md b/index.md index aa2c6103..2c6fc0ff 100644 --- a/index.md +++ b/index.md @@ -1,6 +1,6 @@ # foo.zone -> This site was generated at 2023-12-10T07:56:06+02:00 by `Gemtexter` +> This site was generated at 2023-12-10T11:38:24+02:00 by `Gemtexter` ``` |\---/| @@ -33,6 +33,7 @@ If you reach this site via the modern web, please read this: ### Posts +[2023-12-10 - Bash Golf Part 3](./gemfeed/2023-12-10-bash-golf-part-3.md) [2023-11-11 - 'Mind Management' book notes](./gemfeed/2023-11-11-mind-management-book-notes.md) [2023-10-29 - KISS static web photo albums with `photoalbum.sh`](./gemfeed/2023-10-29-kiss-static-web-photo-albums-with-photoalbum.sh.md) [2023-09-25 - DTail usage examples](./gemfeed/2023-09-25-dtail-usage-examples.md) diff --git a/uptime-stats.md b/uptime-stats.md index 3c476c6d..99c18725 100644 --- a/uptime-stats.md +++ b/uptime-stats.md @@ -1,6 +1,6 @@ # My machine uptime stats -> This site was last updated at 2023-12-10T07:56:06+02:00 +> This site was last updated at 2023-12-10T11:38:24+02:00 The following stats were collected via `uptimed` on all of my personal computers over many years and the output was generated by `guprecords`, the global uptime records stats analyser of mine. -- cgit v1.2.3 From 2cce4c76f0b3e792852397b3c52d7b6c5b711877 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 10 Dec 2023 11:46:22 +0200 Subject: Update content for md --- gemfeed/2023-12-10-bash-golf-part-3.md | 2 +- index.md | 2 +- uptime-stats.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gemfeed/2023-12-10-bash-golf-part-3.md b/gemfeed/2023-12-10-bash-golf-part-3.md index 46cd231f..7735bcb7 100644 --- a/gemfeed/2023-12-10-bash-golf-part-3.md +++ b/gemfeed/2023-12-10-bash-golf-part-3.md @@ -253,7 +253,7 @@ baz foo ``` -What happened? The variable `foo` (declared with `local`) is available in the function it was declared in and in all other functions down the call stack! We can even modify the value of `foo', and the change will be visible up the call stack. It's not a global variable; on the last line, `echo "$foo"` echoes the global variable content. +What happened? The variable `foo` (declared with `local`) is available in the function it was declared in and in all other functions down the call stack! We can even modify the value of `foo`, and the change will be visible up the call stack. It's not a global variable; on the last line, `echo "$foo"` echoes the global variable content. ## `if` conditionals diff --git a/index.md b/index.md index 2c6fc0ff..c6faf620 100644 --- a/index.md +++ b/index.md @@ -1,6 +1,6 @@ # foo.zone -> This site was generated at 2023-12-10T11:38:24+02:00 by `Gemtexter` +> This site was generated at 2023-12-10T11:46:05+02:00 by `Gemtexter` ``` |\---/| diff --git a/uptime-stats.md b/uptime-stats.md index 99c18725..c9a6bfee 100644 --- a/uptime-stats.md +++ b/uptime-stats.md @@ -1,6 +1,6 @@ # My machine uptime stats -> This site was last updated at 2023-12-10T11:38:24+02:00 +> This site was last updated at 2023-12-10T11:46:05+02:00 The following stats were collected via `uptimed` on all of my personal computers over many years and the output was generated by `guprecords`, the global uptime records stats analyser of mine. -- cgit v1.2.3 From 60ade7e934dd65eac561099d92ea923b4e197463 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 10 Dec 2023 17:12:14 +0200 Subject: Update content for md --- .../2021-05-16-personal-bash-coding-style-guide.md | 64 ++++++++++++---------- index.md | 2 +- uptime-stats.md | 2 +- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/gemfeed/2021-05-16-personal-bash-coding-style-guide.md b/gemfeed/2021-05-16-personal-bash-coding-style-guide.md index 8eebbbe0..58bb7e76 100644 --- a/gemfeed/2021-05-16-personal-bash-coding-style-guide.md +++ b/gemfeed/2021-05-16-personal-bash-coding-style-guide.md @@ -27,13 +27,13 @@ These are my modifications to the Google Guide. Google recommends using always... -``` +```bash #!/bin/bash ``` ... as the shebang line, but that does not work on all Unix and Unix-like operating systems (e.g., the *BSDs don't have Bash installed to /bin/bash). Better is: -``` +```bash #!/usr/bin/env bash ``` @@ -51,7 +51,7 @@ I hit the 80 character line length quicker with the four spaces than with two sp Google recommends breaking up long pipes like this: -``` +```bash # All fits on one line command1 | command2 @@ -64,7 +64,7 @@ command1 \ I think there is a better way like the following, which is less noisy. The pipe | already indicates the Bash that another command is expected, thus making the explicit line breaks with \ obsolete: -``` +```bash # Long commands command1 | command2 | @@ -72,11 +72,13 @@ command1 | command4 ``` +> Update: It's 2023 now, and I have changed my mind. I think Google's way is the better one. It may be a bit more to type, but the leading `|` are a nice eye catcher, so you know immediately what is going on! + ### Quoting your variables Google recommends always quote your variables. Generally, it would be best if you did that only for variables where you are unsure about the content/values of the variables (e.g., content is from an external input source and may contain whitespace or other special characters). In my opinion, the code will become quite noisy when you always quote your variables like this: -``` +```bash greet () { local -r greeting="${1}" local -r name="${2}" @@ -86,7 +88,7 @@ greet () { In this particular example, I agree that you should quote them as you don't know the input (are there, for example, whitespace characters?). But if you are sure that you are only using simple bare words, then I think that the code looks much cleaner when you do this instead: -``` +```bash say_hello_to_paul () { local -r greeting=Hello local -r name=Paul @@ -96,7 +98,7 @@ say_hello_to_paul () { You see, I also omitted the curly braces { } around the variables. I only use the curly braces around variables when it makes the code either easier/clearer to read or if it is necessary to use them: -``` +```bash declare FOO=bar # Curly braces around FOO are necessary echo "foo${FOO}baz" @@ -108,7 +110,7 @@ A few more words on always quoting the variables: For the sake of consistency (a Google recommends using the built-in commands over available external commands where possible: -``` +```bash # Prefer this: addition=$(( X + Y )) substitution="${string/#foo/bar}" @@ -132,7 +134,7 @@ I even didn't get started with what you can do with awk (especially GNU Awk), a Bash does not support a boolean type. I tend just to use the strings 'yes' and 'no' here. I used 0 for false and 1 for true for some time, but I think that the yes/no strings are easier to read. Yes, the Bash script would need to perform string comparisons on every check, but if performance is crucial to you, you wouldn't want to use a Bash script anyway, correct? -``` +```bash declare -r SUGAR_FREE=yes declare -r I_NEED_THE_BUZZ=no @@ -153,14 +155,13 @@ buy_soda $I_NEED_THE_BUZZ Google is in the opinion that eval should be avoided. I think so too. They list these examples in their guide: -``` +```bash # What does this set? # Did it succeed? In part or whole? eval $(set_my_variables) # What happens if one of the returned values has a space in it? variable="$(eval some_function)" - ``` However, if I want to read variables from another file, I don't have to use eval here. I only have to source the file: @@ -195,7 +196,7 @@ The downside is that ShellCheck won't be able to follow the dynamic sourcing any When I do list processing in Bash, I prefer to use pipes. You can chain them through Bash functions as well, which is pretty neat. Usually, my list processing scripts are of a structure like this: -``` +```bash filter_lines () { echo 'Start filtering lines in a fancy way!' >&2 grep ... | sed .... @@ -239,35 +240,38 @@ I often refactor existing Bash code. That leads me to add and removing function The solution is to use of the "assign-then-shift"-method, which goes like this: "local -r var1=$1; shift; local -r var2=$1; shift". The idea is that you only use "$1" to assign function arguments to named (better readable) local function variables. You will never have to bother about "$2" or above. That is very useful when you constantly refactor your code and remove or add function arguments. It's something that I picked up from a colleague (a pure Bash wizard) some time ago: -``` +```bash some_function () { local -r param_foo="$1"; shift local -r param_baz="$1"; shift local -r param_bay="$1"; shift - ... + + # ... } ``` Want to add a param_baz? Just do this: -``` +```bash some_function () { local -r param_foo="$1"; shift local -r param_bar="$1"; shift local -r param_baz="$1"; shift local -r param_bay="$1"; shift - ... + + # ... } ``` Want to remove param_foo? Nothing easier than that: -``` +```bash some_function () { local -r param_bar="$1"; shift local -r param_baz="$1"; shift local -r param_bay="$1"; shift - ... + + # ... } ``` @@ -277,7 +281,7 @@ As you can see, I didn't need to change any other assignments within the functio I call this the paranoid mode. The Bash will stop executing when a command exits with a status not equal to 0: -``` +```bash set -e grep -q foo <<< bar echo Jo @@ -285,14 +289,14 @@ echo Jo Here 'Jo' will never be printed out as the grep didn't find any match. It's unrealistic for most scripts to run in paranoid mode purely, so there must be a way to add exceptions. Critical Bash scripts of mine tend to look like this: -``` +```bash #!/usr/bin/env bash set -e some_function () { - .. some critical code - ... + # .. some critical code + # ... set +e # Grep might fail, but that's OK now @@ -300,11 +304,11 @@ some_function () { local -i ec=$? set -e - .. critical code continues ... + # .. critical code continues ... if [[ $ec -ne 0 ]]; then - ... + : # ... fi - ... + # ... } ``` @@ -316,7 +320,7 @@ There are also a couple of things I've learned from Google's guide. The following looks like a valid Bash code: -``` +```bash if [[ "${my_var}" > 3 ]]; then # True for 4, false for 22. do_something @@ -325,7 +329,7 @@ fi ... but it is probably an unintended lexicographical comparison. A correct way would be: -``` +```bash if (( my_var > 3 )); then do_something fi @@ -333,7 +337,7 @@ fi or -``` +```bash if [[ "${my_var}" -gt 3 ]]; then do_something fi @@ -345,7 +349,7 @@ I have never used the PIPESTATUS variable before. I knew that it's there, but I The PIPESTATUS variable in Bash allows checking of the return code from all parts of a pipe. If it's only necessary to check the success or failure of the whole pipe, then the following is acceptable: -``` +```bash tar -cf - ./* | ( cd "${dir}" && tar -xf - ) if (( PIPESTATUS[0] != 0 || PIPESTATUS[1] != 0 )); then echo "Unable to tar files to ${dir}" >&2 @@ -354,7 +358,7 @@ fi However, as PIPESTATUS will be overwritten as soon as you do any other command, if you need to act differently on errors based on where it happened in the pipe, you'll need to assign PIPESTATUS to another variable immediately after running the command (don't forget that [ is a command and will wipe out PIPESTATUS). -``` +```bash tar -cf - ./* | ( cd "${DIR}" && tar -xf - ) return_codes=( "${PIPESTATUS[@]}" ) if (( return_codes[0] != 0 )); then diff --git a/index.md b/index.md index c6faf620..645cac30 100644 --- a/index.md +++ b/index.md @@ -1,6 +1,6 @@ # foo.zone -> This site was generated at 2023-12-10T11:46:05+02:00 by `Gemtexter` +> This site was generated at 2023-12-10T17:11:56+02:00 by `Gemtexter` ``` |\---/| diff --git a/uptime-stats.md b/uptime-stats.md index c9a6bfee..5e60c28c 100644 --- a/uptime-stats.md +++ b/uptime-stats.md @@ -1,6 +1,6 @@ # My machine uptime stats -> This site was last updated at 2023-12-10T11:46:05+02:00 +> This site was last updated at 2023-12-10T17:11:56+02:00 The following stats were collected via `uptimed` on all of my personal computers over many years and the output was generated by `guprecords`, the global uptime records stats analyser of mine. -- cgit v1.2.3 From 171e61019c783ed393d7516a0b6b64a7c65646e6 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Tue, 9 Jan 2024 18:45:34 +0200 Subject: Update content for md --- ...23-08-18-site-reliability-engineering-part-1.md | 10 +- ...23-08-19-site-reliability-engineering-part-2.md | 50 ------- ...23-08-20-site-reliability-engineering-part-3.md | 59 -------- ...23-11-19-site-reliability-engineering-part-2.md | 50 +++++++ ...24-01-09-site-reliability-engineering-part-3.md | 57 ++++++++ gemfeed/index.md | 4 +- index.md | 6 +- uptime-stats.md | 148 ++++++++++----------- 8 files changed, 191 insertions(+), 193 deletions(-) delete mode 100644 gemfeed/2023-08-19-site-reliability-engineering-part-2.md delete mode 100644 gemfeed/2023-08-20-site-reliability-engineering-part-3.md create mode 100644 gemfeed/2023-11-19-site-reliability-engineering-part-2.md create mode 100644 gemfeed/2024-01-09-site-reliability-engineering-part-3.md diff --git a/gemfeed/2023-08-18-site-reliability-engineering-part-1.md b/gemfeed/2023-08-18-site-reliability-engineering-part-1.md index 4ce87aaf..7d1d098c 100644 --- a/gemfeed/2023-08-18-site-reliability-engineering-part-1.md +++ b/gemfeed/2023-08-18-site-reliability-engineering-part-1.md @@ -2,11 +2,11 @@ > Published at 2023-08-18T22:43:47+03:00 -The universe of Site Reliability Engineering (SRE) is like an intricate tapestry woven with diverse technology, culture, and personal grit threads. Site Reliability Engineering is one of the most demanding jobs. With all the facets, it's impossible to get bored. There is always a new challenge to master, and there is always a new technology to tinker with. It's not just technical; it's also about communication, collaboration and teamwork. I am currently employed as a Principal Site Reliability Engineer and will try to share what SRE is about in this blog series. +The universe of Site Reliability Engineering (SRE) is like an intricate tapestry woven with diverse technology, culture, and personal grit threads. Site Reliability Engineering is one of the most demanding jobs. With all the facets, it's impossible to get bored. There is always a new challenge to master, and there is always a new technology to tinker with. It's not just technical; it's also about communication, collaboration and teamwork. I am currently employed as a Site Reliability Engineer and will try to share what SRE is about in this blog series. [2023-08-18 Site Reliability Engineering - Part 1: SRE and Organizational Culture (You are currently reading this)](./2023-08-18-site-reliability-engineering-part-1.md) -[2023-08-19 Site Reliability Engineering - Part 2: Operational Balance in SRE](./2023-08-19-site-reliability-engineering-part-2.md) -[2023-08-20 Site Reliability Engineering - Part 3: On-Call Culture and the Human Aspect](./2023-08-20-site-reliability-engineering-part-3.md) +[2023-11-19 Site Reliability Engineering - Part 2: Operational Balance in SRE](./2023-11-19-site-reliability-engineering-part-2.md) +[2024-01-09 Site Reliability Engineering - Part 3: On-Call Culture and the Human Aspect](./2024-01-09-site-reliability-engineering-part-3.md) ``` ▓▓▓▓░░ @@ -36,7 +36,7 @@ At the heart of SRE lies the proactive mindset of "prevention over cure." Tradit Another defining SRE idea concept the "error budget." This ingenious framework accepts that no system is flawless. Failures are inevitable. However, instead of being punitive, the culture here is to accept, learn, and iterate. By providing teams with a "budget" for errors, organisations create an environment where innovation is encouraged, and failures are viewed as learning opportunities. -But SRE isn't just about technology and metrics; it's deeply human. It challenges the "hero culture" that plagues many IT teams. While individual heroics might occasionally save the day, a sustainable model requires collective expertise. An SRE culture recognises that heroes achieve their best within teams, negating the need for a hero-centric environment. This philosophy promotes a balanced on-call experience, emphasising the importance of trust, ownership, effective communication, and collaboration as cornerstones of team success. I personally have fallen into the hero trap, and know it's unsustainable to be the only go-to person for every problem. +But SRE isn't just about technology and metrics; it's also human. It challenges the "hero culture" that plagues many IT teams. While individual heroics might occasionally save the day, a sustainable model requires collective expertise. An SRE culture recognises that heroes achieve their best within teams, negating the need for a hero-centric environment. This philosophy promotes a balanced on-call experience, emphasising the importance of trust, ownership, effective communication, and collaboration as cornerstones of team success. I personally have fallen into the hero trap, and know it's unsustainable to be the only go-to person for every arising problem. Additionally, the SRE model requires good documentation. However, it's essential ensuring that this documentation undergoes the same quality checks as code, reinforcing effective onboarding, training and communication. @@ -52,7 +52,7 @@ Organisations with the implementation of SLIs, SLOs and error budgets are alread Continue with the second part of this series: -[2023-08-19 Site Reliability Engineering - Part 2: Operational Balance in SRE](./2023-08-19-site-reliability-engineering-part-2.md) +[2023-11-19 Site Reliability Engineering - Part 2: Operational Balance in SRE](./2023-11-19-site-reliability-engineering-part-2.md) E-Mail your comments to `paul@nospam.buetow.org` :-) diff --git a/gemfeed/2023-08-19-site-reliability-engineering-part-2.md b/gemfeed/2023-08-19-site-reliability-engineering-part-2.md deleted file mode 100644 index b3e908f4..00000000 --- a/gemfeed/2023-08-19-site-reliability-engineering-part-2.md +++ /dev/null @@ -1,50 +0,0 @@ -# Site Reliability Engineering - Part 2: Operational Balance in SRE - -> Published at 2023-08-19T00:18:18+03:00 - -This is the second part of my Site Reliability Engineering (SRE) series. I am currently employed as a Principal Site Reliability Engineer and will try to share what SRE is about in this blog series. - -[2023-08-18 Site Reliability Engineering - Part 1: SRE and Organizational Culture](./2023-08-18-site-reliability-engineering-part-1.md) -[2023-08-19 Site Reliability Engineering - Part 2: Operational Balance in SRE (You are currently reading this)](./2023-08-19-site-reliability-engineering-part-2.md) -[2023-08-20 Site Reliability Engineering - Part 3: On-Call Culture and the Human Aspect](./2023-08-20-site-reliability-engineering-part-3.md) - -``` -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣾⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⣾⠿⠿⠿⠶⠾⠿⠿⣿⣿⣿⣿⣿⣿⠿⠿⠶⠶⠿⠿⠿⣷⠀⠀⠀⠀ -⠀⠀⠀⣸⢿⣆⠀⠀⠀⠀⠀⠀⠀⠙⢿⡿⠉⠀⠀⠀⠀⠀⠀⠀⣸⣿⡆⠀⠀⠀ -⠀⠀⢠⡟⠀⢻⣆⠀⠀⠀⠀⠀⠀⠀⣾⣧⠀⠀⠀⠀⠀⠀⠀⣰⡟⠀⢻⡄⠀⠀ -⠀⢀⣾⠃⠀⠀⢿⡄⠀⠀⠀⠀⠀⢠⣿⣿⡀⠀⠀⠀⠀⠀⢠⡿⠀⠀⠘⣷⡀⠀ -⠀⣼⣏⣀⣀⣀⣈⣿⡀⠀⠀⠀⠀⣸⣿⣿⡇⠀⠀⠀⠀⢀⣿⣃⣀⣀⣀⣸⣧⠀ -⠀⢻⣿⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⣿⣿⣿⣿⠀⠀⠀⠀⠈⢿⣿⣿⣿⣿⣿⡿⠀ -⠀⠀⠉⠛⠛⠛⠋⠁⠀⠀⠀⠀⢸⣿⣿⣿⣿⡆⠀⠀⠀⠀⠈⠙⠛⠛⠛⠉⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠴⠶⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠶⠦⠀⠀ -``` - -## Operational Balance in SRE: Finding the Equilibrium in Reliability and Velocity - -Site Reliability Engineering has established itself as more than just a set of best practices or methodologies. Instead, it stands as a beacon of operational excellence, which guides engineering teams through the turbulent waters of modern software development and system management. - -In the universe of software production, two fundamental forces are often at odds: The drive for rapid feature release (velocity) and the need for system reliability. Traditionally, the faster teams moved, the more risk was introduced into systems. SRE offers a approach to mitigate these conflicting drives through concepts like error budgets and SLIs/SLOs. These mechanisms offer a tangible metric, allowing teams to quantify how much they can push changes while ensuring they don't compromise system health. Thus, the error budget becomes a balancing act, where teams weigh the trade-offs between innovation and reliability. - -An important part of this balance is the dichotomy between operations and coding. According to SRE principles, an engineer should ideally spend an equal amount of time on operations work and coding - 50% on each. This isn't just a random metric; it's a reflection of the value SRE places on both maintaining operational excellence and progressing forward with innovations. This balance ensures that while SREs are solving today's problems, they are also preparing for tomorrow's challenges. - -However, not all operational tasks are equal. SRE differentiates between "ops work" and "toil". While ops work is integral to system maintenance and can provide value, toil represents repetitive, mundane tasks which offer little value in the long run. Recognising and minimising toil is crucial. A culture that allows engineers to drown in toil stifles innovation and growth. Hence, an organisation's approach to toil indicates its operational health and commitment to balance. - -A cornerstone of achieving operational balance lies in the tools and processes SREs use. Effective monitoring, observability tools, and ensuring that tools can handle high cardinality data are foundational. These aren't just technical requisites but reflective of an organisational culture prioritising proactive problem-solving. By having systems that effectively flag potential issues before they escalate, SREs can maintain the balance between system stability and forward momentum. - -Moreover, operational balance isn't just a technological or process challenge; it's a human one. The health of on-call engineers is as crucial as the health of the services they manage. On-call postmortems, continuous feedback loops, and recognising gaps (be it tooling, operational expertise, or resources) ensure that the human elements of operations are noticed. - -In conclusion, operational balance in SRE isn't static thing but an ongoing journey. It requires organisations to constantly evaluate their practices, tools, and, most importantly, their culture. By achieving this balance, organisations can ensure that they have time for innovation while maintaining the robustness and reliability of their systems, resulting in sustainable long-term success. - -That all sounds very romantic. The truth is, it's brutal to archive the perfect balance. No system will ever be perfect. But at least we should aim for it! - -Continue with the third part of this series: - -[2023-08-20 Site Reliability Engineering - Part 3: On-Call Culture and the Human Aspect](./2023-08-20-site-reliability-engineering-part-3.md) - -E-Mail your comments to `paul@nospam.buetow.org` :-) - -[Back to the main site](../) diff --git a/gemfeed/2023-08-20-site-reliability-engineering-part-3.md b/gemfeed/2023-08-20-site-reliability-engineering-part-3.md deleted file mode 100644 index 831eb156..00000000 --- a/gemfeed/2023-08-20-site-reliability-engineering-part-3.md +++ /dev/null @@ -1,59 +0,0 @@ -# Site Reliability Engineering - Part 3: On-Call Culture and the Human Aspect - -> Published at 2023-08-20T12:17:56+03:00 - -This is the third part of my Site Reliability Engineering (SRE) series. I am currently employed as a Principal Site Reliability Engineer and will try to share what SRE is about in this blog series. - -[2023-08-18 Site Reliability Engineering - Part 1: SRE and Organizational Culture](./2023-08-18-site-reliability-engineering-part-1.md) -[2023-08-19 Site Reliability Engineering - Part 2: Operational Balance in SRE](./2023-08-19-site-reliability-engineering-part-2.md) -[2023-08-20 Site Reliability Engineering - Part 3: On-Call Culture and the Human Aspect (You are currently reading this)](./2023-08-20-site-reliability-engineering-part-3.md) - -``` - ..--""""----.. - .-" ..--""""--.j-. - .-" .-" .--.""--.. - .-" .-" ..--"-. \/ ; - .-" .-"_.--..--"" ..--' "-. : - .' .' / `. \..--"" __ _ \ ; - :.__.-" \ / .' ( )"-. Y - ; ;: ( ) ( ). \ - .': /:: : \ \ - .'.-"\._ _.-" ; ; ( ) .-. ( ) \ - " `.""" .j" : : \ ; ; \ - bug /"""""/ ; ( ) "" :.( ) \ - /\ / : \ \`.: _ \ - : `. / ; `( ) (\/ :" \ \ - \ `. : "-.(_)_.' t-' ; - \ `. ; ..--": - `. `. : ..--"" : - `. "-. ; ..--"" ; - `. "-.:_..--"" ..--" - `. : ..--"" - "-. : ..--"" - "-.;_..--"" - -``` - -## On-Call Culture and the Human Aspect: Prioritising Well-being in the Realm of Reliability - -Site Reliability Engineering is synonymous with ensuring system reliability, but the human factor is an often-underestimated part of this discipline. Ensuring an healthy on-call culture is as critical as any technical solution. The well-being of the engineers is an important factor. - -Firstly, a healthy on-call rotation is about more than just managing and responding to incidents. It's about the entire ecosystem that supports this practice. This involves reducing pain points, offering mentorship, rapid iteration, and ensuring that engineers have the right tools and processes. One ceavat is, that engineers should be willing to learn. Especially in on-call rotation embedding SREs with other engineers (for example Software Engineers or QA Engineers), it's difficult to motivate everyone to engage. QA Engineers want to test the software, Software Engineers want to implement new features; they don't want to troubleshoot and debug production incidents. It can be depressing for the mentoring SRE. - -Furthermore, the metrics that measure the success of an on-call experience are only sometimes straightforward. While one might assume that fewer pages translate to better on-call expertise (which is true to a degree, as who wants to receive a page out of office hours?), it's not always the volume of pages that matters most. Trust, ownership, accountability, and effective communication play the important roles. - -An important part is giving feedback about the on-call experience to ensure continuous learning. If alerts are mostly noise, they should be tuned or even eliminated. If alerts are actionable, can recurring tasks be automated? If there are knowledge gaps, is the documentation not good enough? Continuous retrospection ensures that not only do systems evolve, but the experience for the on-call engineers becomes progressively better. - -Onboarding for on-call duties is a crucial aspect of ensuring the reliability and efficiency of systems. This process involves equipping new team members with the knowledge, tools, and support to handle incidents confidently. It begins with an overview of the system architecture and common challenges, followed by training on monitoring tools, alerting mechanisms, and incident response protocols. Shadowing experienced on-call engineers can offer practical exposure. Too often, new engineers are thrown into the cold water without proper onboarding and training because the more experienced engineers are too busy fire-fighting production issues in the first place. - -An always-on, always-alert culture can lead to burnout. Engineers should be encouraged to recognise their limits, take breaks, and seek support when needed. This isn't just about individual health; a burnt-out engineer can have cascading effects on the entire team and the systems they manage. A successful on-call culture ensures that while systems are kept running, the engineers are kept happy, healthy, and supported. The more experienced engineers should take time to mentor the junior engineers, but the junior engineers should also be fully engaged, try to investigate and learn new things by themselves. - -For the junior engineer, it's too easy to fall back and ask the experts in the team every time an issue arises. This seems reasonable, but serving recipes for solving production issues on a silver tablet won't scale forever, as there are infinite scenarios of how production systems can break. So every engineer should learn to debug, troubleshoot and resolve production incidents independently. The experts will still be there for guidance and step in when the junior gets stuck after trying, but the experts should also learn to step down so that lesser experienced engineers can step up and learn. But mistakes can always happen here; that's why having a blameless on-call culture is essential. - -A blameless on-call culture is a must for a safe and collaborative environment where engineers can effectively respond to incidents without fear of retribution. This approach acknowledges that mistakes are a natural part of the learning and innovation process. When individuals are assured they won't be punished for errors, they're more likely to openly discuss mistakes, allowing the entire team to learn and grow from each incident. Furthermore, a blameless culture promotes psychological safety, enhances job satisfaction, reduces burnout, and ensures that talent remains committed and engaged. - -The fourth part of this blog series will be published soon :-) - -E-Mail your comments to `paul@nospam.buetow.org` :-) - -[Back to the main site](../) diff --git a/gemfeed/2023-11-19-site-reliability-engineering-part-2.md b/gemfeed/2023-11-19-site-reliability-engineering-part-2.md new file mode 100644 index 00000000..0db86f50 --- /dev/null +++ b/gemfeed/2023-11-19-site-reliability-engineering-part-2.md @@ -0,0 +1,50 @@ +# Site Reliability Engineering - Part 2: Operational Balance in SRE + +> Published at 2023-11-19T00:18:18+03:00 + +This is the second part of my Site Reliability Engineering (SRE) series. I am currently employed as a Site Reliability Engineer and will try to share what SRE is about in this blog series. + +[2023-08-18 Site Reliability Engineering - Part 1: SRE and Organizational Culture](./2023-08-18-site-reliability-engineering-part-1.md) +[2023-11-19 Site Reliability Engineering - Part 2: Operational Balance in SRE (You are currently reading this)](./2023-11-19-site-reliability-engineering-part-2.md) +[2024-01-09 Site Reliability Engineering - Part 3: On-Call Culture and the Human Aspect](./2024-01-09-site-reliability-engineering-part-3.md) + +``` +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣾⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⣾⠿⠿⠿⠶⠾⠿⠿⣿⣿⣿⣿⣿⣿⠿⠿⠶⠶⠿⠿⠿⣷⠀⠀⠀⠀ +⠀⠀⠀⣸⢿⣆⠀⠀⠀⠀⠀⠀⠀⠙⢿⡿⠉⠀⠀⠀⠀⠀⠀⠀⣸⣿⡆⠀⠀⠀ +⠀⠀⢠⡟⠀⢻⣆⠀⠀⠀⠀⠀⠀⠀⣾⣧⠀⠀⠀⠀⠀⠀⠀⣰⡟⠀⢻⡄⠀⠀ +⠀⢀⣾⠃⠀⠀⢿⡄⠀⠀⠀⠀⠀⢠⣿⣿⡀⠀⠀⠀⠀⠀⢠⡿⠀⠀⠘⣷⡀⠀ +⠀⣼⣏⣀⣀⣀⣈⣿⡀⠀⠀⠀⠀⣸⣿⣿⡇⠀⠀⠀⠀⢀⣿⣃⣀⣀⣀⣸⣧⠀ +⠀⢻⣿⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⣿⣿⣿⣿⠀⠀⠀⠀⠈⢿⣿⣿⣿⣿⣿⡿⠀ +⠀⠀⠉⠛⠛⠛⠋⠁⠀⠀⠀⠀⢸⣿⣿⣿⣿⡆⠀⠀⠀⠀⠈⠙⠛⠛⠛⠉⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠴⠶⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠿⠶⠦⠀⠀ +``` + +## Operational Balance in SRE: Finding the Equilibrium in Reliability and Velocity + +Site Reliability Engineering has established itself as more than just a set of best practices or methodologies. Instead, it stands as a beacon of operational excellence, which guides engineering teams through the turbulent waters of modern software development and system management. + +In the universe of software production, two fundamental forces are often at odds: The drive for rapid feature release (velocity) and the need for system reliability. Traditionally, the faster teams moved, the more risk was introduced into systems. SRE offers a approach to mitigate these conflicting drives through concepts like error budgets and SLIs/SLOs. These mechanisms offer a tangible metric, allowing teams to quantify how much they can push changes while ensuring they don't compromise system health. Thus, the error budget becomes a balancing act, where teams weigh the trade-offs between innovation and reliability. + +An important part of this balance is the dichotomy between operations and coding. According to SRE principles, an e