From cd60a353054abfae9609f71fbab0e97640d0a877 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 22 Jun 2025 23:04:01 +0300 Subject: Update content for html --- gemfeed/2008-06-26-perl-poetry.html | 148 +- gemfeed/2010-04-09-standard-ml-and-haskell.html | 166 +- .../2010-05-09-the-fype-programming-language.html | 78 +- .../2011-05-07-perl-daemon-service-framework.html | 120 +- .../2014-03-24-the-fibonacci.pl.c-polyglot.html | 188 +- ...2-05-run-debian-on-your-phone-with-debroid.html | 184 +- ...20-object-oriented-programming-with-ansi-c.html | 66 +- ...021-05-16-personal-bash-coding-style-guide.html | 276 +- ...5-gemtexter-one-bash-script-to-rule-it-all.html | 36 +- ...2-08-27-gemtexter-1.1.0-lets-gemtext-again.html | 34 +- ...-tried-emacs-but-i-switched-back-to-neovim.html | 8 +- ...03-25-gemtexter-2.0.0-lets-gemtext-again-2.html | 18 +- ...iling-guprecords:-uptime-records-with-raku.html | 2 +- ...3-06-01-kiss-server-monitoring-with-gogios.html | 102 +- ...07-21-gemtexter-2.1.0-lets-gemtext-again-3.html | 10 +- gemfeed/2023-09-25-dtail-usage-examples.html | 106 +- ...static-web-photo-albums-with-photoalbum.sh.html | 118 +- gemfeed/2023-12-10-bash-golf-part-3.html | 238 +- .../2024-01-13-one-reason-why-i-love-openbsd.html | 10 +- ...-04-01-KISS-high-availability-with-OpenBSD.html | 200 +- ...03-projects-i-currently-dont-have-time-for.html | 12 +- ...2024-06-23-terminal-multiplexing-with-tmux.html | 164 +- gemfeed/2024-07-05-random-weird-things.html | 212 +- ...10-02-gemtexter-3.0.0-lets-gemtext-again-4.html | 2 +- ...4-12-03-f3s-kubernetes-with-freebsd-part-2.html | 128 +- gemfeed/2024-12-15-random-helix-themes.html | 110 +- ...5-02-01-f3s-kubernetes-with-freebsd-part-3.html | 266 +- gemfeed/2025-02-08-random-weird-things-ii.html | 128 +- ...025-03-05-sharing-on-social-media-with-gos.html | 38 +- ...5-04-05-f3s-kubernetes-with-freebsd-part-4.html | 348 +-- ...rminal-multiplexing-with-tmux-fish-edition.html | 16 +- ...5-05-11-f3s-kubernetes-with-freebsd-part-5.html | 836 +++--- .../DRAFT-f3s-kubernetes-with-freebsd-part-6.html | 130 +- gemfeed/atom.xml | 2964 ++++++++++---------- 34 files changed, 3731 insertions(+), 3731 deletions(-) (limited to 'gemfeed') diff --git a/gemfeed/2008-06-26-perl-poetry.html b/gemfeed/2008-06-26-perl-poetry.html index 79f8860c..70db4f02 100644 --- a/gemfeed/2008-06-26-perl-poetry.html +++ b/gemfeed/2008-06-26-perl-poetry.html @@ -59,44 +59,44 @@ _~~|~/_|_|__/|~~~~~~~ | / ~~~~~ | | ~~~~~~~~ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
#!/usr/bin/perl
+
#!/usr/bin/perl
 
-# (C) 2006 by Paul C. Buetow
+# (C) 2006 by Paul C. Buetow
 
-goto library for study $math;
-BEGIN { s/earching/ books/ 
-and read $them, $at, $the } library:
+goto library for study $math;
+BEGIN { s/earching/ books/ 
+and read $them, $at, $the } library:
 
-our $topics, cos and tan, 
-require strict; import { of, tied $patience };
+our $topics, cos and tan, 
+require strict; import { of, tied $patience };
 
-do { int'egrate'; sub trade; };
-do { exp'onentize' and abs'olutize' };
-study and study and study and study;
+do { int'egrate'; sub trade; };
+do { exp'onentize' and abs'olutize' };
+study and study and study and study;
 
-foreach $topic ({of, math}) {
-you, m/ay /go, to, limits }
+foreach $topic ({of, math}) {
+you, m/ay /go, to, limits }
 
-do { not qw/erk / unless $success 
-and m/ove /o;$n and study };
+do { not qw/erk / unless $success 
+and m/ove /o;$n and study };
 
-do { int'egrate'; sub trade; };
-do { exp'onentize' and abs'olutize' };
-study and study and study and study;
+do { int'egrate'; sub trade; };
+do { exp'onentize' and abs'olutize' };
+study and study and study and study;
 
-grep /all/, exp'onents' and cos'inuses';
-/seek results/ for @all, log'4rithms';
+grep /all/, exp'onents' and cos'inuses';
+/seek results/ for @all, log'4rithms';
 
-'you' =~ m/ay /go, not home 
-unless each %book ne#ars
-$completion;
+'you' =~ m/ay /go, not home 
+unless each %book ne#ars
+$completion;
 
-do { int'egrate'; sub trade; };
-do { exp'onentize' and abs'olutize' };
+do { int'egrate'; sub trade; };
+do { exp'onentize' and abs'olutize' };
 
-#at
-home: //ig,'nore', time and sleep $very =~ s/tr/on/g;
-__END__
+#at
+home: //ig,'nore', time and sleep $very =~ s/tr/on/g;
+__END__
 
 

@@ -106,47 +106,47 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
#!/usr/bin/perl
+
#!/usr/bin/perl
 
-# (C) 2006 by Paul C. Buetow
+# (C) 2006 by Paul C. Buetow
 
-Christmas:{time;#!!!
+Christmas:{time;#!!!
 
-Children: do tell $wishes;
+Children: do tell $wishes;
 
-Santa: for $each (@children) { 
-BEGIN { read $each, $their, wishes and study them; use Memoize#ing
+Santa: for $each (@children) { 
+BEGIN { read $each, $their, wishes and study them; use Memoize#ing
 
-} use constant gift, 'wrapping'; 
-package Gifts; pack $each, gift and bless $each and goto deliver
-or do import if not local $available,!!! HO, HO, HO;
+} use constant gift, 'wrapping'; 
+package Gifts; pack $each, gift and bless $each and goto deliver
+or do import if not local $available,!!! HO, HO, HO;
 
-redo Santa, pipe $gifts, to_childs;
-redo Santa and do return if last one, is, delivered; 
+redo Santa, pipe $gifts, to_childs;
+redo Santa and do return if last one, is, delivered; 
 
-deliver: gift and require diagnostics if our $gifts ,not break;
-do{ use NEXT; time; tied $gifts} if broken and dump the, broken, ones;
-The_children: sleep and wait for (each %gift) and try { to => untie $gifts };
+deliver: gift and require diagnostics if our $gifts ,not break;
+do{ use NEXT; time; tied $gifts} if broken and dump the, broken, ones;
+The_children: sleep and wait for (each %gift) and try { to => untie $gifts };
 
-redo Santa, pipe $gifts, to_childs;
-redo Santa and do return if last one, is, delivered; 
+redo Santa, pipe $gifts, to_childs;
+redo Santa and do return if last one, is, delivered; 
 
-The_christmas_tree: formline s/ /childrens/, $gifts;
-alarm and warn if not exists $Christmas{ tree}, @t, $ENV{HOME};  
-write <<EMail
- to the parents to buy a new christmas tree!!!!111
- and send the
-EMail
-;wait and redo deliver until defined local $tree;
+The_christmas_tree: formline s/ /childrens/, $gifts;
+alarm and warn if not exists $Christmas{ tree}, @t, $ENV{HOME};  
+write <<EMail
+ to the parents to buy a new christmas tree!!!!111
+ and send the
+EMail
+;wait and redo deliver until defined local $tree;
 
-redo Santa, pipe $gifts, to_childs;
-redo Santa and do return if last one, is, delivered ;}
+redo Santa, pipe $gifts, to_childs;
+redo Santa and do return if last one, is, delivered ;}
 
-END {} our $mission and do sleep until next Christmas ;}
+END {} our $mission and do sleep until next Christmas ;}
 
-__END__
+__END__
 
-This is perl, v5.8.8 built for i386-freebsd-64int
+This is perl, v5.8.8 built for i386-freebsd-64int
 

shopping.pl


@@ -155,35 +155,35 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
#!/usr/bin/perl
+
#!/usr/bin/perl
 
-# (C) 2007 by Paul C. Buetow
+# (C) 2007 by Paul C. Buetow
 
-BEGIN{} goto mall for $shopping; 
+BEGIN{} goto mall for $shopping; 
 
-m/y/; mall: seek$s, cool products(), { to => $sell };
-for $their (@business) { to:; earn:; a:; lot:; of:; money: }
+m/y/; mall: seek$s, cool products(), { to => $sell };
+for $their (@business) { to:; earn:; a:; lot:; of:; money: }
 
-do not goto home and exit mall if exists $new{product};
-foreach $of (q(uality rich products)){} package products; 
+do not goto home and exit mall if exists $new{product};
+foreach $of (q(uality rich products)){} package products; 
 
-our $news; do tell cool products() and do{ sub#tract
-cool{ $products and shift @the, @bad, @ones;
+our $news; do tell cool products() and do{ sub#tract
+cool{ $products and shift @the, @bad, @ones;
 
-do bless [q(uality)], $products 
-and return not undef $stuff if not (local $available) }};
+do bless [q(uality)], $products 
+and return not undef $stuff if not (local $available) }};
 
-do { study and study and study for cool products() }
-and do { seek $all, cool products(), { to => $buy } };
+do { study and study and study for cool products() }
+and do { seek $all, cool products(), { to => $buy } };
 
-do { write $them, $down } and do { order: foreach (@case) { package s } };
-goto home if not exists $more{money} or die q(uerying) ;for( @money){};
+do { write $them, $down } and do { order: foreach (@case) { package s } };
+goto home if not exists $more{money} or die q(uerying) ;for( @money){};
 
-at:;home: do { END{} and:; rest:; a:; bit: exit $shopping } 
-and sleep until unpack$ing, cool products();
+at:;home: do { END{} and:; rest:; a:; bit: exit $shopping } 
+and sleep until unpack$ing, cool products();
 
-__END__
-This is perl, v5.8.8 built for i386-freebsd-64int
+__END__
+This is perl, v5.8.8 built for i386-freebsd-64int
 

More...


diff --git a/gemfeed/2010-04-09-standard-ml-and-haskell.html b/gemfeed/2010-04-09-standard-ml-and-haskell.html index 51041c21..cf394c68 100644 --- a/gemfeed/2010-04-09-standard-ml-and-haskell.html +++ b/gemfeed/2010-04-09-standard-ml-and-haskell.html @@ -40,10 +40,10 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
datatype ’a multi
-	= EMPTY
-	| ELEM of ’a
-	| UNION of ’a multi * ’a multi
+
datatype ’a multi
+	= EMPTY
+	| ELEM of ’a
+	| UNION of ’a multi * ’a multi
 

Haskell:
@@ -52,11 +52,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
data (Eq a) => Multi a
-    = Empty
-    | Elem a
-    | Union (Multi a) (Multi a)
-    deriving Show
+
data (Eq a) => Multi a
+    = Empty
+    | Elem a
+    | Union (Multi a) (Multi a)
+    deriving Show
 

Processing a multi


@@ -67,12 +67,12 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
fun number (EMPTY) _ = 0
-	| number (ELEM x) w = if x = w then 1 else 0
-	| number (UNION (x,y)) w = (number x w) + (number y w)
-fun test_number w = number (UNION (EMPTY, \
-    UNION (ELEM 4, UNION (ELEM 6, \
-    UNION (UNION (ELEM 4, ELEM 4), EMPTY))))) w 
+
fun number (EMPTY) _ = 0
+	| number (ELEM x) w = if x = w then 1 else 0
+	| number (UNION (x,y)) w = (number x w) + (number y w)
+fun test_number w = number (UNION (EMPTY, \
+    UNION (ELEM 4, UNION (ELEM 6, \
+    UNION (UNION (ELEM 4, ELEM 4), EMPTY))))) w 
 

Haskell:
@@ -81,11 +81,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
number Empty _ = 0
-number (Elem x) w = if x == w then 1 else 0
-test_number w = number (Union Empty \
-    (Union (Elem 4) (Union (Elem 6) \
-    (Union (Union (Elem 4) (Elem 4)) Empty)))) w
+
number Empty _ = 0
+number (Elem x) w = if x == w then 1 else 0
+test_number w = number (Union Empty \
+    (Union (Elem 4) (Union (Elem 6) \
+    (Union (Union (Elem 4) (Elem 4)) Empty)))) w
 

Simplify function


@@ -96,19 +96,19 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
fun simplify (UNION (x,y)) =
-    let fun is_empty (EMPTY) = true | is_empty _ = false
-        val x’ = simplify x
-        val y’ = simplify y
-    in if (is_empty x’) andalso (is_empty y’)
-            then EMPTY
-       else if (is_empty x’)
-            then y’
-       else if (is_empty y’)
-            then x’
-       else UNION (x’, y’)
-    end
-  | simplify x = x
+
fun simplify (UNION (x,y)) =
+    let fun is_empty (EMPTY) = true | is_empty _ = false
+        val x’ = simplify x
+        val y’ = simplify y
+    in if (is_empty x’) andalso (is_empty y’)
+            then EMPTY
+       else if (is_empty x’)
+            then y’
+       else if (is_empty y’)
+            then x’
+       else UNION (x’, y’)
+    end
+  | simplify x = x
 

Haskell:
@@ -117,17 +117,17 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
simplify (Union x y)
-    | (isEmpty x’) && (isEmpty y’) = Empty
-    | isEmpty x’ = y’
-    | isEmpty y’ = x’
-    | otherwise = Union x’ y’
-    where
-        isEmpty Empty = True
-        isEmpty _ = False
-        x’ = simplify x
-        y’ = simplify y
-simplify x = x
+
simplify (Union x y)
+    | (isEmpty x’) && (isEmpty y’) = Empty
+    | isEmpty x’ = y’
+    | isEmpty y’ = x’
+    | otherwise = Union x’ y’
+    where
+        isEmpty Empty = True
+        isEmpty _ = False
+        x’ = simplify x
+        y’ = simplify y
+simplify x = x
 

Delete all


@@ -138,12 +138,12 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
fun delete_all m w =
-    let fun delete_all’ (ELEM x) = if x = w then EMPTY else ELEM x
-          | delete_all’ (UNION (x,y)) = UNION (delete_all’ x, delete_all’ y)
-          | delete_all’ x = x
-    in simplify (delete_all’ m)
-    end
+
fun delete_all m w =
+    let fun delete_all’ (ELEM x) = if x = w then EMPTY else ELEM x
+          | delete_all’ (UNION (x,y)) = UNION (delete_all’ x, delete_all’ y)
+          | delete_all’ x = x
+    in simplify (delete_all’ m)
+    end
 

Haskell:
@@ -152,11 +152,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
delete_all m w = simplify (delete_all’ m)
-    where
-        delete_all’ (Elem x) = if x == w then Empty else Elem x
-        delete_all’ (Union x y) = Union (delete_all’ x) (delete_all’ y)
-        delete_all’ x = x
+
delete_all m w = simplify (delete_all’ m)
+    where
+        delete_all’ (Elem x) = if x == w then Empty else Elem x
+        delete_all’ (Union x y) = Union (delete_all’ x) (delete_all’ y)
+        delete_all’ x = x
 

Delete one


@@ -167,21 +167,21 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
fun delete_one m w =
-    let fun delete_one’ (UNION (x,y)) =
-            let val (x’, deleted) = delete_one’ x
-                in if deleted
-                   then (UNION (x’, y), deleted)
-                   else let val (y’, deleted) = delete_one’ y
-                       in (UNION (x, y’), deleted)
-                   end
-                end
-          | delete_one’ (ELEM x) =
-            if x = w then (EMPTY, true) else (ELEM x, false)
-          | delete_one’ x = (x, false)
-            val (m’, _) = delete_one’ m
-        in simplify m’
-    end
+
fun delete_one m w =
+    let fun delete_one’ (UNION (x,y)) =
+            let val (x’, deleted) = delete_one’ x
+                in if deleted
+                   then (UNION (x’, y), deleted)
+                   else let val (y’, deleted) = delete_one’ y
+                       in (UNION (x, y’), deleted)
+                   end
+                end
+          | delete_one’ (ELEM x) =
+            if x = w then (EMPTY, true) else (ELEM x, false)
+          | delete_one’ x = (x, false)
+            val (m’, _) = delete_one’ m
+        in simplify m’
+    end
 

Haskell:
@@ -190,19 +190,19 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
delete_one m w = do
-    let (m’, _) = delete_one’ m
-    simplify m’
-    where
-        delete_one’ (Union x y) =
-            let (x’, deleted) = delete_one’ x
-            in if deleted
-                then (Union x’ y, deleted)
-                else let (y’, deleted) = delete_one’ y
-                    in (Union x y’, deleted)
-        delete_one’ (Elem x) =
-            if x == w then (Empty, True) else (Elem x, False)
-        delete_one’ x = (x, False)
+
delete_one m w = do
+    let (m’, _) = delete_one’ m
+    simplify m’
+    where
+        delete_one’ (Union x y) =
+            let (x’, deleted) = delete_one’ x
+            in if deleted
+                then (Union x’ y, deleted)
+                else let (y’, deleted) = delete_one’ y
+                    in (Union x y’, deleted)
+        delete_one’ (Elem x) =
+            if x == w then (Empty, True) else (Elem x, False)
+        delete_one’ x = (x, False)
 

Higher-order functions


diff --git a/gemfeed/2010-05-09-the-fype-programming-language.html b/gemfeed/2010-05-09-the-fype-programming-language.html index 12c13460..87265746 100644 --- a/gemfeed/2010-05-09-the-fype-programming-language.html +++ b/gemfeed/2010-05-09-the-fype-programming-language.html @@ -69,12 +69,12 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
typedef struct {
-   Tupel *p_tupel_argv; // Contains command line options
-   List *p_list_token; // Initial list of token
-   Hash *p_hash_syms; // Symbol table
-   char *c_basename;
-} Fype;
+
typedef struct {
+   Tupel *p_tupel_argv; // Contains command line options
+   List *p_list_token; // Initial list of token
+   Hash *p_hash_syms; // Symbol table
+   char *c_basename;
+} Fype;
 

And here is a snippet from the primary Fype "class implementation":
@@ -83,53 +83,53 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
Fype*
-fype_new() {
-   Fype *p_fype = malloc(sizeof(Fype));
+
Fype*
+fype_new() {
+   Fype *p_fype = malloc(sizeof(Fype));
 
-   p_fype->p_hash_syms = hash_new(512);
-   p_fype->p_list_token = list_new();
-   p_fype->p_tupel_argv = tupel_new();
-   p_fype->c_basename = NULL;
+   p_fype->p_hash_syms = hash_new(512);
+   p_fype->p_list_token = list_new();
+   p_fype->p_tupel_argv = tupel_new();
+   p_fype->c_basename = NULL;
 
-   garbage_init();
+   garbage_init();
 
-   return (p_fype);
-}
+   return (p_fype);
+}
 
-void
-fype_delete(Fype *p_fype) {
-   argv_tupel_delete(p_fype->p_tupel_argv);
+void
+fype_delete(Fype *p_fype) {
+   argv_tupel_delete(p_fype->p_tupel_argv);
 
-   hash_iterate(p_fype->p_hash_syms, symbol_cleanup_hash_syms_cb);
-   hash_delete(p_fype->p_hash_syms);
+   hash_iterate(p_fype->p_hash_syms, symbol_cleanup_hash_syms_cb);
+   hash_delete(p_fype->p_hash_syms);
 
-   list_iterate(p_fype->p_list_token, token_ref_down_cb);
-   list_delete(p_fype->p_list_token);
+   list_iterate(p_fype->p_list_token, token_ref_down_cb);
+   list_delete(p_fype->p_list_token);
 
-   if (p_fype->c_basename)
-      free(p_fype->c_basename);
+   if (p_fype->c_basename)
+      free(p_fype->c_basename);
 
-   garbage_destroy();
-}
+   garbage_destroy();
+}
 
-int
-fype_run(int i_argc, char **pc_argv) {
-   Fype *p_fype = fype_new();
+int
+fype_run(int i_argc, char **pc_argv) {
+   Fype *p_fype = fype_new();
 
-   // argv: Maintains command line options
-   argv_run(p_fype, i_argc, pc_argv);
+   // argv: Maintains command line options
+   argv_run(p_fype, i_argc, pc_argv);
 
-   // scanner: Creates a list of token
-   scanner_run(p_fype);
+   // scanner: Creates a list of token
+   scanner_run(p_fype);
 
-   // interpret: Interpret the list of token
-   interpret_run(p_fype);
+   // interpret: Interpret the list of token
+   interpret_run(p_fype);
 
-   fype_delete(p_fype);
+   fype_delete(p_fype);
 
-   return (0);
-}
+   return (0);
+}
 

Data types


diff --git a/gemfeed/2011-05-07-perl-daemon-service-framework.html b/gemfeed/2011-05-07-perl-daemon-service-framework.html index 24325930..9467224b 100644 --- a/gemfeed/2011-05-07-perl-daemon-service-framework.html +++ b/gemfeed/2011-05-07-perl-daemon-service-framework.html @@ -58,14 +58,14 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
# Starting
- ./bin/perldaemon start (or shortcut ./control start)
+
# Starting
+ ./bin/perldaemon start (or shortcut ./control start)
 
-# Stopping
- ./bin/perldaemon stop (or shortcut ./control stop)
+# Stopping
+ ./bin/perldaemon stop (or shortcut ./control stop)
 
-# Alternatively: Starting in foreground 
-./bin/perldaemon start daemon.daemonize=no (or shortcut ./control foreground)
+# Alternatively: Starting in foreground 
+./bin/perldaemon start daemon.daemonize=no (or shortcut ./control foreground)
 

To stop a daemon from running in foreground mode, "Ctrl+C" must be hit. To see more available startup options run "./control" without any argument.
@@ -78,30 +78,30 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
pb@titania:~/svn/utils/perldaemon/trunk$ ./control keys
-# Path to the logfile
-daemon.logfile=./log/perldaemon.log
+
pb@titania:~/svn/utils/perldaemon/trunk$ ./control keys
+# Path to the logfile
+daemon.logfile=./log/perldaemon.log
 
-# The amount of seconds until the next event look takes place
-daemon.loopinterval=1
+# The amount of seconds until the next event look takes place
+daemon.loopinterval=1
 
-# Path to the modules dir
-daemon.modules.dir=./lib/PerlDaemonModules
+# Path to the modules dir
+daemon.modules.dir=./lib/PerlDaemonModules
 
-# Specifies either the daemon should run in daemon or foreground mode
-daemon.daemonize=yes
+# Specifies either the daemon should run in daemon or foreground mode
+daemon.daemonize=yes
 
-# Path to the pidfile
-daemon.pidfile=./run/perldaemon.pid
+# Path to the pidfile
+daemon.pidfile=./run/perldaemon.pid
 
-# Each module should run every run interval seconds
-daemon.modules.runinterval=3
+# Each module should run every run interval seconds
+daemon.modules.runinterval=3
 
-# Path to the alive file (is touched every loop interval seconds, usable for monitoring)
-daemon.alivefile=./run/perldaemon.alive
+# Path to the alive file (is touched every loop interval seconds, usable for monitoring)
+daemon.alivefile=./run/perldaemon.alive
 
-# Specifies the working directory
-daemon.wd=./
+# Specifies the working directory
+daemon.wd=./
 

Example


@@ -112,17 +112,17 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
$ ./control keys | grep daemon.loopinterval
-daemon.loopinterval=1
-$ ./control keys daemon.loopinterval=10 | grep daemon.loopinterval
-daemon.loopinterval=10
-$ ./control start daemon.loopinterval=10; sleep 10; tail -n 2 log/perldaemon.log
-Starting daemon now...
-Mon Jun 13 11:29:27 2011 (PID 2838): Triggering PerlDaemonModules::ExampleModule 
-(last triggered before 10.002106s; carry: 7.002106s; wanted interval: 3s)
-Mon Jun 13 11:29:27 2011 (PID 2838): ExampleModule Test 2
-$ ./control stop
-Stopping daemon now...
+
$ ./control keys | grep daemon.loopinterval
+daemon.loopinterval=1
+$ ./control keys daemon.loopinterval=10 | grep daemon.loopinterval
+daemon.loopinterval=10
+$ ./control start daemon.loopinterval=10; sleep 10; tail -n 2 log/perldaemon.log
+Starting daemon now...
+Mon Jun 13 11:29:27 2011 (PID 2838): Triggering PerlDaemonModules::ExampleModule 
+(last triggered before 10.002106s; carry: 7.002106s; wanted interval: 3s)
+Mon Jun 13 11:29:27 2011 (PID 2838): ExampleModule Test 2
+$ ./control stop
+Stopping daemon now...
 

If you want to change that property forever, either edit perldaemon.conf or do this:
@@ -131,7 +131,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
$ ./control keys daemon.loopinterval=10 > new.conf; mv new.conf conf/perldaemon.conf
+
$ ./control keys daemon.loopinterval=10 > new.conf; mv new.conf conf/perldaemon.conf
 

HiRes event loop


@@ -148,35 +148,35 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
package PerlDaemonModules::ExampleModule;
+
package PerlDaemonModules::ExampleModule;
 
-use strict;
-use warnings;
+use strict;
+use warnings;
 
-sub new ($$$) {
-  my ($class, $conf) = @_;
+sub new ($$$) {
+  my ($class, $conf) = @_;
 
-  my $self = bless { conf => $conf }, $class;
+  my $self = bless { conf => $conf }, $class;
 
-  # Store some private module stuff
-  $self->{counter} = 0;
+  # Store some private module stuff
+  $self->{counter} = 0;
 
-  return $self;
-}
+  return $self;
+}
 
-# Runs periodically in a loop (set interval in perldaemon.conf)
-sub do ($) {
-  my $self = shift;
-  my $conf = $self->{conf};
-  my $logger = $conf->{logger};
+# Runs periodically in a loop (set interval in perldaemon.conf)
+sub do ($) {
+  my $self = shift;
+  my $conf = $self->{conf};
+  my $logger = $conf->{logger};
 
-  # Calculate some private module stuff
-  my $count = ++$self->{counter};
+  # Calculate some private module stuff
+  my $count = ++$self->{counter};
 
-  $logger->logmsg("ExampleModule Test $count");
-}
+  $logger->logmsg("ExampleModule Test $count");
+}
 
-1;
+1;
 

Your own module


@@ -187,11 +187,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
 cd ./lib/PerlDaemonModules/
- cp ExampleModule.pm YourModule.pm
- vi YourModule.pm
- cd -
- ./bin/perldaemon restart (or shortcurt ./control restart)
+
 cd ./lib/PerlDaemonModules/
+ cp ExampleModule.pm YourModule.pm
+ vi YourModule.pm
+ cd -
+ ./bin/perldaemon restart (or shortcurt ./control restart)
 

Now watch ./log/perldaemon.log closely. It is a good practice to test your modules in 'foreground mode' (see above how to do that).
diff --git a/gemfeed/2014-03-24-the-fibonacci.pl.c-polyglot.html b/gemfeed/2014-03-24-the-fibonacci.pl.c-polyglot.html index 8bb53e07..d80da161 100644 --- a/gemfeed/2014-03-24-the-fibonacci.pl.c-polyglot.html +++ b/gemfeed/2014-03-24-the-fibonacci.pl.c-polyglot.html @@ -27,47 +27,47 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
#include <stdio.h>
+
#include <stdio.h>
 
-#define $arg function_argument
-#define my int
-#define sub int
-#define BEGIN int main(void)
+#define $arg function_argument
+#define my int
+#define sub int
+#define BEGIN int main(void)
 
-my $arg;
+my $arg;
 
-sub hello() {
-    printf("Hello, welcome to the Fibonacci Numbers!\n");
-    printf("This program is all, valid C and C++ and Perl and Raku code!\n");
-    printf("It calculates all fibonacci numbers from 0 to 9!\n\n");
-    return 0;
-}
+sub hello() {
+    printf("Hello, welcome to the Fibonacci Numbers!\n");
+    printf("This program is all, valid C and C++ and Perl and Raku code!\n");
+    printf("It calculates all fibonacci numbers from 0 to 9!\n\n");
+    return 0;
+}
 
-sub fibonacci() {
-    my $n = $arg;
+sub fibonacci() {
+    my $n = $arg;
 
-    if ($n < 2) {
-        return $n;
-    }
+    if ($n < 2) {
+        return $n;
+    }
 
-    $arg = $n - 1;
-    my $fib1 = fibonacci();
-    $arg = $n - 2;
-    my $fib2 = fibonacci();
+    $arg = $n - 1;
+    my $fib1 = fibonacci();
+    $arg = $n - 2;
+    my $fib2 = fibonacci();
 
-    return $fib1 + $fib2;
-}
+    return $fib1 + $fib2;
+}
 
-BEGIN {
-    hello();
-    my $i = 0;
+BEGIN {
+    hello();
+    my $i = 0;
 
-    while ($i <= 10) {
-        $arg = $i;
-        printf("fib(%d) = %d\n", $i, fibonacci());
-        $i++;
-    }
-}
+    while ($i <= 10) {
+        $arg = $i;
+        printf("fib(%d) = %d\n", $i, fibonacci());
+        $i++;
+    }
+}
 

You can find the full source code at GitHub:
@@ -80,41 +80,41 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
% gcc fibonacci.pl.raku.c -o fibonacci
-% ./fibonacci
-Hello, welcome to the Fibonacci Numbers!
-This program is all, valid C and C++ and Perl and Raku code!
-It calculates all fibonacci numbers from 0 to 9!
+
% gcc fibonacci.pl.raku.c -o fibonacci
+% ./fibonacci
+Hello, welcome to the Fibonacci Numbers!
+This program is all, valid C and C++ and Perl and Raku code!
+It calculates all fibonacci numbers from 0 to 9!
 
-fib(0) = 0
-fib(1) = 1
-fib(2) = 1
-fib(3) = 2
-fib(4) = 3
-fib(5) = 5
-fib(6) = 8
-fib(7) = 13
-fib(8) = 21
-fib(9) = 34
-fib(10) = 55
+fib(0) = 0
+fib(1) = 1
+fib(2) = 1
+fib(3) = 2
+fib(4) = 3
+fib(5) = 5
+fib(6) = 8
+fib(7) = 13
+fib(8) = 21
+fib(9) = 34
+fib(10) = 55
 
-% g++ fibonacci.pl.raku.c -o fibonacci
-% ./fibonacci
-Hello, welcome to the Fibonacci Numbers!
-This program is all, valid C and C++ and Perl and Raku code!
-It calculates all fibonacci numbers from 0 to 9!
+% g++ fibonacci.pl.raku.c -o fibonacci
+% ./fibonacci
+Hello, welcome to the Fibonacci Numbers!
+This program is all, valid C and C++ and Perl and Raku code!
+It calculates all fibonacci numbers from 0 to 9!
 
-fib(0) = 0
-fib(1) = 1
-fib(2) = 1
-fib(3) = 2
-fib(4) = 3
-fib(5) = 5
-fib(6) = 8
-fib(7) = 13
-fib(8) = 21
-fib(9) = 34
-fib(10) = 55
+fib(0) = 0
+fib(1) = 1
+fib(2) = 1
+fib(3) = 2
+fib(4) = 3
+fib(5) = 5
+fib(6) = 8
+fib(7) = 13
+fib(8) = 21
+fib(9) = 34
+fib(10) = 55
 

Let's run it with Perl and Raku


@@ -123,39 +123,39 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
% perl fibonacci.pl.raku.c
-Hello, welcome to the Fibonacci Numbers!
-This program is all, valid C and C++ and Perl and Raku code!
-It calculates all fibonacci numbers from 0 to 9!
+
% perl fibonacci.pl.raku.c
+Hello, welcome to the Fibonacci Numbers!
+This program is all, valid C and C++ and Perl and Raku code!
+It calculates all fibonacci numbers from 0 to 9!
 
-fib(0) = 0
-fib(1) = 1
-fib(2) = 1
-fib(3) = 2
-fib(4) = 3
-fib(5) = 5
-fib(6) = 8
-fib(7) = 13
-fib(8) = 21
-fib(9) = 34
-fib(10) = 55
+fib(0) = 0
+fib(1) = 1
+fib(2) = 1
+fib(3) = 2
+fib(4) = 3
+fib(5) = 5
+fib(6) = 8
+fib(7) = 13
+fib(8) = 21
+fib(9) = 34
+fib(10) = 55
 
-% raku fibonacci.pl.raku.c
-Hello, welcome to the Fibonacci Numbers!
-This program is all, valid C and C++ and Perl and Raku code!
-It calculates all fibonacci numbers from 0 to 9!
+% raku fibonacci.pl.raku.c
+Hello, welcome to the Fibonacci Numbers!
+This program is all, valid C and C++ and Perl and Raku code!
+It calculates all fibonacci numbers from 0 to 9!
 
-fib(0) = 0
-fib(1) = 1
-fib(2) = 1
-fib(3) = 2
-fib(4) = 3
-fib(5) = 5
-fib(6) = 8
-fib(7) = 13
-fib(8) = 21
-fib(9) = 34
-fib(10) = 55
+fib(0) = 0
+fib(1) = 1
+fib(2) = 1
+fib(3) = 2
+fib(4) = 3
+fib(5) = 5
+fib(6) = 8
+fib(7) = 13
+fib(8) = 21
+fib(9) = 34
+fib(10) = 55
 

It's entertaining to play with :-).
diff --git a/gemfeed/2015-12-05-run-debian-on-your-phone-with-debroid.html b/gemfeed/2015-12-05-run-debian-on-your-phone-with-debroid.html index 520bb8c7..4a01cc45 100644 --- a/gemfeed/2015-12-05-run-debian-on-your-phone-with-debroid.html +++ b/gemfeed/2015-12-05-run-debian-on-your-phone-with-debroid.html @@ -56,24 +56,24 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
sudo dnf install debootstrap
-# 5g
-dd if=/dev/zero of=jessie.img bs=$[ 1024 * 1024 ] \
-  count=$[ 1024 * 5 ]
+
sudo dnf install debootstrap
+# 5g
+dd if=/dev/zero of=jessie.img bs=$[ 1024 * 1024 ] \
+  count=$[ 1024 * 5 ]
 
-# Show used loop devices
-sudo losetup -f
-# Store the next free one to $loop
-loop=loopN
-sudo losetup /dev/$loop jessie.img
+# Show used loop devices
+sudo losetup -f
+# Store the next free one to $loop
+loop=loopN
+sudo losetup /dev/$loop jessie.img
 
-mkdir jessie
-sudo mkfs.ext4 /dev/$loop
-sudo mount /dev/$loop jessie
-sudo debootstrap --foreign --variant=minbase \
-  --arch armel jessie jessie/ \
-  http://http.debian.net/debian
-sudo umount jessie
+mkdir jessie
+sudo mkfs.ext4 /dev/$loop
+sudo mount /dev/$loop jessie
+sudo debootstrap --foreign --variant=minbase \
+  --arch armel jessie jessie/ \
+  http://http.debian.net/debian
+sudo umount jessie
 

Copy Debian image to the phone


@@ -84,42 +84,42 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
adb root && adb wait-for-device && adb shell
-mkdir -p /storage/sdcard1/Linux/jessie
-exit
+
adb root && adb wait-for-device && adb shell
+mkdir -p /storage/sdcard1/Linux/jessie
+exit
 
-# Sparse image problem, may be too big for copying otherwise
-gzip jessie.img
-# Copy over
-adb push jessie.img.gz /storage/sdcard1/Linux/jessie.img.gz
-adb shell
-cd /storage/sdcard1/Linux
-gunzip jessie.img.gz
+# Sparse image problem, may be too big for copying otherwise
+gzip jessie.img
+# Copy over
+adb push jessie.img.gz /storage/sdcard1/Linux/jessie.img.gz
+adb shell
+cd /storage/sdcard1/Linux
+gunzip jessie.img.gz
 
-# Show used loop devices
-losetup -f
-# Store the next free one to $loop
-loop=loopN
+# Show used loop devices
+losetup -f
+# Store the next free one to $loop
+loop=loopN
 
-# Use the next free one (replace the loop number)
-losetup /dev/block/$loop $(pwd)/jessie.img
-mount -t ext4 /dev/block/$loop $(pwd)/jessie
+# Use the next free one (replace the loop number)
+losetup /dev/block/$loop $(pwd)/jessie.img
+mount -t ext4 /dev/block/$loop $(pwd)/jessie
 
-# Bind-Mound proc, dev, sys`
-busybox mount --bind /proc $(pwd)/jessie/proc
-busybox mount --bind /dev $(pwd)/jessie/dev
-busybox mount --bind /dev/pts $(pwd)/jessie/dev/pts
-busybox mount --bind /sys $(pwd)/jessie/sys
+# Bind-Mound proc, dev, sys`
+busybox mount --bind /proc $(pwd)/jessie/proc
+busybox mount --bind /dev $(pwd)/jessie/dev
+busybox mount --bind /dev/pts $(pwd)/jessie/dev/pts
+busybox mount --bind /sys $(pwd)/jessie/sys
 
-# Bind-Mound the rest of Android
-mkdir -p $(pwd)/jessie/storage/sdcard{0,1}
-busybox mount --bind /storage/emulated \
-  $(pwd)/jessie/storage/sdcard0
-busybox mount --bind /storage/sdcard1 \
-  $(pwd)/jessie/storage/sdcard1
+# Bind-Mound the rest of Android
+mkdir -p $(pwd)/jessie/storage/sdcard{0,1}
+busybox mount --bind /storage/emulated \
+  $(pwd)/jessie/storage/sdcard0
+busybox mount --bind /storage/sdcard1 \
+  $(pwd)/jessie/storage/sdcard1
 
-# Check mounts
-mount | grep jessie
+# Check mounts
+mount | grep jessie
 

Second debootstrap stage


@@ -130,11 +130,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
chroot $(pwd)/jessie /bin/bash -l
-export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin
-/debootstrap/debootstrap --second-stage
-exit # Leave chroot
-exit # Leave adb shell
+
chroot $(pwd)/jessie /bin/bash -l
+export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin
+/debootstrap/debootstrap --second-stage
+exit # Leave chroot
+exit # Leave adb shell
 

Setup of various scripts


@@ -145,36 +145,36 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
# Install script jessie.sh
-adb push storage/sdcard1/Linux/jessie.sh /storage/sdcard/Linux/jessie.sh
-adb shell
-cd /storage/sdcard1/Linux
-sh jessie.sh enter
+
# Install script jessie.sh
+adb push storage/sdcard1/Linux/jessie.sh /storage/sdcard/Linux/jessie.sh
+adb shell
+cd /storage/sdcard1/Linux
+sh jessie.sh enter
 
-# Bashrc
-cat <<END >~/.bashrc
-export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
-export EDITOR=vim
-hostname $(cat /etc/hostname)
-END
+# Bashrc
+cat <<END >~/.bashrc
+export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
+export EDITOR=vim
+hostname $(cat /etc/hostname)
+END
 
-# Fixing an error message while loading the profile
-sed -i s#id#/usr/bin/id# /etc/profile
+# Fixing an error message while loading the profile
+sed -i s#id#/usr/bin/id# /etc/profile
 
-# Setting the hostname
-echo phobos > /etc/hostname
-echo 127.0.0.1 phobos > /etc/hosts
-hostname phobos
+# Setting the hostname
+echo phobos > /etc/hostname
+echo 127.0.0.1 phobos > /etc/hosts
+hostname phobos
 
-# Apt-sources
-cat <<END > sources.list
-deb http://ftp.uk.debian.org/debian/ jessie main contrib non-free
-deb-src http://ftp.uk.debian.org/debian/ jessie main contrib non-free
-END
-apt-get update
-apt-get upgrade
-apt-get dist-upgrade
-exit # Exit chroot
+# Apt-sources
+cat <<END > sources.list
+deb http://ftp.uk.debian.org/debian/ jessie main contrib non-free
+deb-src http://ftp.uk.debian.org/debian/ jessie main contrib non-free
+END
+apt-get update
+apt-get upgrade
+apt-get dist-upgrade
+exit # Exit chroot
 

Entering Debroid and enable a service


@@ -185,19 +185,19 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
sh jessie.sh enter
+
sh jessie.sh enter
 
-# Setup example serice uptimed
-apt-get install uptimed
-cat <<END > /etc/rc.debroid
-export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
-service uptimed status &>/dev/null || service uptimed start
-exit 0
-END
+# Setup example serice uptimed
+apt-get install uptimed
+cat <<END > /etc/rc.debroid
+export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
+service uptimed status &>/dev/null || service uptimed start
+exit 0
+END
 
-chmod 0755 /etc/rc.debroid
-exit # Exit chroot
-exit # Exit adb shell
+chmod 0755 /etc/rc.debroid
+exit # Exit chroot
+exit # Exit adb shell
 

Include to Android startup:


@@ -208,10 +208,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
adb push data/local/userinit.sh /data/local/userinit.sh
-adb shell
-chmod +x /data/local/userinit.sh
-exit
+
adb push data/local/userinit.sh /data/local/userinit.sh
+adb shell
+chmod +x /data/local/userinit.sh
+exit
 

Reboot & test! Enjoy!
diff --git a/gemfeed/2016-11-20-object-oriented-programming-with-ansi-c.html b/gemfeed/2016-11-20-object-oriented-programming-with-ansi-c.html index 247c0959..f1b51b47 100644 --- a/gemfeed/2016-11-20-object-oriented-programming-with-ansi-c.html +++ b/gemfeed/2016-11-20-object-oriented-programming-with-ansi-c.html @@ -34,37 +34,37 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
#include <stdio.h>
+
#include <stdio.h>
 
-typedef struct {
-    double (*calculate)(const double, const double);
-    char *name;
-} something_s;
+typedef struct {
+    double (*calculate)(const double, const double);
+    char *name;
+} something_s;
 
-double multiplication(const double a, const double b) {
-    return a * b;
-}
+double multiplication(const double a, const double b) {
+    return a * b;
+}
 
-double division(const double a, const double b) {
-    return a / b;
-}
+double division(const double a, const double b) {
+    return a / b;
+}
 
-int main(void) {
-    something_s mult = (something_s) {
-        .calculate = multiplication,
-        .name = "Multiplication"
-    };
+int main(void) {
+    something_s mult = (something_s) {
+        .calculate = multiplication,
+        .name = "Multiplication"
+    };
 
-    something_s div = (something_s) {
-        .calculate = division,
-        .name = "Division"
-    };
+    something_s div = (something_s) {
+        .calculate = division,
+        .name = "Division"
+    };
 
-    const double a = 3, b = 2;
+    const double a = 3, b = 2;
 
-    printf("%s(%f, %f) => %f\n", mult.name, a, b, mult.calculate(a,b));
-    printf("%s(%f, %f) => %f\n", div.name, a, b, div.calculate(a,b));
-}
+    printf("%s(%f, %f) => %f\n", mult.name, a, b, mult.calculate(a,b));
+    printf("%s(%f, %f) => %f\n", div.name, a, b, div.calculate(a,b));
+}
 

As you can see, you can call the function (pointed by the function pointer) with the same syntax as in C++ or Java:
@@ -73,8 +73,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
printf("%s(%f, %f) => %f\n", mult.name, a, b, mult.calculate(a,b));
-printf("%s(%f, %f) => %f\n", div.name, a, b, div.calculate(a,b));
+
printf("%s(%f, %f) => %f\n", mult.name, a, b, mult.calculate(a,b));
+printf("%s(%f, %f) => %f\n", div.name, a, b, div.calculate(a,b));
 

However, that's just syntactic sugar for:
@@ -83,8 +83,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
printf("%s(%f, %f) => %f\n", mult.name, a, b, (*mult.calculate)(a,b));
-printf("%s(%f, %f) => %f\n", div.name, a, b, (*div.calculate)(a,b));
+
printf("%s(%f, %f) => %f\n", mult.name, a, b, (*mult.calculate)(a,b));
+printf("%s(%f, %f) => %f\n", div.name, a, b, (*div.calculate)(a,b));
 

Output:
@@ -93,10 +93,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
pbuetow ~/git/blog/source [38268]% gcc oop-c-example.c -o oop-c-example
-pbuetow ~/git/blog/source [38269]% ./oop-c-example
-Multiplication(3.000000, 2.000000) => 6.000000
-Division(3.000000, 2.000000) => 1.500000
+
pbuetow ~/git/blog/source [38268]% gcc oop-c-example.c -o oop-c-example
+pbuetow ~/git/blog/source [38269]% ./oop-c-example
+Multiplication(3.000000, 2.000000) => 6.000000
+Division(3.000000, 2.000000) => 1.500000
 

Not complicated at all, but nice to know and helps to make the code easier to read!
@@ -109,7 +109,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
mult.calculate(mult,a,b));
+
mult.calculate(mult,a,b));
 

Real object oriented programming with C


diff --git a/gemfeed/2021-05-16-personal-bash-coding-style-guide.html b/gemfeed/2021-05-16-personal-bash-coding-style-guide.html index 48192cd5..75c528c3 100644 --- a/gemfeed/2021-05-16-personal-bash-coding-style-guide.html +++ b/gemfeed/2021-05-16-personal-bash-coding-style-guide.html @@ -66,7 +66,7 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
#!/bin/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:
@@ -75,7 +75,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
#!/usr/bin/env bash
+
#!/usr/bin/env bash
 

Two space soft-tabs indentation


@@ -96,14 +96,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
# All fits on one line
-command1 | command2
+
# All fits on one line
+command1 | command2
 
-# Long commands
-command1 \
-  | command2 \
-  | command3 \
-  | command4
+# Long commands
+command1 \
+  | command2 \
+  | command3 \
+  | command4
 

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:
@@ -112,11 +112,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
# Long commands
-command1 |
-    command2 |
-    command3 |
-    command4
+
# Long commands
+command1 |
+    command2 |
+    command3 |
+    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!
@@ -129,11 +129,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
greet () {
-    local -r greeting="${1}"
-    local -r name="${2}"
-    echo "${greeting} ${name}!"
-}
+
greet () {
+    local -r greeting="${1}"
+    local -r name="${2}"
+    echo "${greeting} ${name}!"
+}
 

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:
@@ -142,11 +142,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
say_hello_to_paul () {
-    local -r greeting=Hello
-    local -r name=Paul
-    echo "$greeting $name!"
-}
+
say_hello_to_paul () {
+    local -r greeting=Hello
+    local -r name=Paul
+    echo "$greeting $name!"
+}
 

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:
@@ -155,9 +155,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
declare FOO=bar
-# Curly braces around FOO are necessary
-echo "foo${FOO}baz"
+
declare FOO=bar
+# Curly braces around FOO are necessary
+echo "foo${FOO}baz"
 

A few more words on always quoting the variables: For the sake of consistency (and for making ShellCheck happy), I am not against quoting everything I encounter. I also think that the larger the Bash script becomes, the more critical it becomes always to quote variables. That's because it will be more likely that you might not remember that some of the functions don't work on values with spaces in them, for example. It's just that I won't quote everything in every small script I write.
@@ -170,13 +170,13 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
# Prefer this:
-addition=$(( X + Y ))
-substitution="${string/#foo/bar}"
+
# Prefer this:
+addition=$(( X + Y ))
+substitution="${string/#foo/bar}"
 
-# Instead of this:
-addition="$(expr "${X}" + "${Y}")"
-substitution="$(echo "${string}" | sed -e 's/^foo/bar/')"
+# Instead of this:
+addition="$(expr "${X}" + "${Y}")"
+substitution="$(echo "${string}" | sed -e 's/^foo/bar/')"
 

I can't entirely agree here. The external commands (especially sed) are much more sophisticated and powerful than the built-in Bash versions. Sed can do much more than the Bash can ever do by itself when it comes to text manipulation (the name "sed" stands for streaming editor, after all).
@@ -197,20 +197,20 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
declare -r SUGAR_FREE=yes
-declare -r I_NEED_THE_BUZZ=no
+
declare -r SUGAR_FREE=yes
+declare -r I_NEED_THE_BUZZ=no
 
-buy_soda () {
-    local -r sugar_free=$1
+buy_soda () {
+    local -r sugar_free=$1
 
-    if [[ $sugar_free == yes ]]; then
-        echo 'Diet Dr. Pepper'
-    else
-        echo 'Pepsi Coke'
-    fi
-}
+    if [[ $sugar_free == yes ]]; then
+        echo 'Diet Dr. Pepper'
+    else
+        echo 'Pepsi Coke'
+    fi
+}
 
-buy_soda $I_NEED_THE_BUZZ
+buy_soda $I_NEED_THE_BUZZ
 

Non-evil alternative to variable assignments via eval


@@ -221,12 +221,12 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
# What does this set?
-# Did it succeed? In part or whole?
-eval $(set_my_variables)
+
# 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)"
+# 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:
@@ -265,39 +265,39 @@ Hello paul, it is Sat 15 May 19:21:12 BST 2021 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
filter_lines () {
-    echo 'Start filtering lines in a fancy way!' >&2
-    grep ... | sed ....
-}
+
filter_lines () {
+    echo 'Start filtering lines in a fancy way!' >&2
+    grep ... | sed ....
+}
 
-process_lines () {
-    echo 'Start processing line by line!' >&2
-    while read -r line; do
-        ... do something and produce a result...
-        echo "$result"
-    done 
-}
+process_lines () {
+    echo 'Start processing line by line!' >&2
+    while read -r line; do
+        ... do something and produce a result...
+        echo "$result"
+    done 
+}
 
-# Do some post-processing of the data
-postprocess_lines () {
-    echo 'Start removing duplicates!' >&2
-    sort -u
-}
+# Do some post-processing of the data
+postprocess_lines () {
+    echo 'Start removing duplicates!' >&2
+    sort -u
+}
 
-genreate_report () {
-    echo 'My boss wants to have a report!' >&2
-    tee outfile.txt
-    wc -l outfile.txt
-}
+genreate_report () {
+    echo 'My boss wants to have a report!' >&2
+    tee outfile.txt
+    wc -l outfile.txt
+}
 
-main () {
-    filter_lines |
-        process_lines |
-        postprocess_lines |
-        generate_report
-}
+main () {
+    filter_lines |
+        process_lines |
+        postprocess_lines |
+        generate_report
+}
 
-main
+main
 

The stdout is always passed as a pipe to the next following stage. The stderr is used for info logging.
@@ -312,13 +312,13 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
some_function () {
-    local -r param_foo="$1"; shift
-    local -r param_baz="$1"; shift
-    local -r param_bay="$1"; shift
+
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:
@@ -327,14 +327,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
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
+
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:
@@ -343,13 +343,13 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
some_function () {
-    local -r param_bar="$1"; shift
-    local -r param_baz="$1"; shift
-    local -r param_bay="$1"; shift
-    
-    # ...
-}
+
some_function () {
+    local -r param_bar="$1"; shift
+    local -r param_baz="$1"; shift
+    local -r param_bay="$1"; shift
+    
+    # ...
+}
 

As you can see, I didn't need to change any other assignments within the function. Of course, you would also need to change the function argument lists at every occasion where the function is invoked - you would do that within the same refactoring session.
@@ -362,9 +362,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
set -e
-grep -q foo <<< bar
-echo Jo
+
set -e
+grep -q foo <<< bar
+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:
@@ -373,26 +373,26 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
#!/usr/bin/env bash
+
#!/usr/bin/env bash
 
-set -e
+set -e
 
-some_function () {
-    # .. some critical code
-    # ...
+some_function () {
+    # .. some critical code
+    # ...
 
-    set +e
-    # Grep might fail, but that's OK now
-    grep ....
-    local -i ec=$?
-    set -e
+    set +e
+    # Grep might fail, but that's OK now
+    grep ....
+    local -i ec=$?
+    set -e
 
-    # .. critical code continues ...
-    if [[ $ec -ne 0 ]]; then
-        : # ...
-    fi
-    # ...
-}
+    # .. critical code continues ...
+    if [[ $ec -ne 0 ]]; then
+        : # ...
+    fi
+    # ...
+}
 

Learned


@@ -407,10 +407,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
if [[ "${my_var}" > 3 ]]; then
-    # True for 4, false for 22.
-    do_something
-fi
+
if [[ "${my_var}" > 3 ]]; then
+    # True for 4, false for 22.
+    do_something
+fi
 

... but it is probably an unintended lexicographical comparison. A correct way would be:
@@ -419,9 +419,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
if (( my_var > 3 )); then
-    do_something
-fi
+
if (( my_var > 3 )); then
+    do_something
+fi
 

or
@@ -430,9 +430,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
if [[ "${my_var}" -gt 3 ]]; then
-    do_something
-fi
+
if [[ "${my_var}" -gt 3 ]]; then
+    do_something
+fi
 

PIPESTATUS


@@ -445,10 +445,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
tar -cf - ./* | ( cd "${dir}" && tar -xf - )
-if (( PIPESTATUS[0] != 0 || PIPESTATUS[1] != 0 )); then
-    echo "Unable to tar files to ${dir}" >&2
-fi
+
tar -cf - ./* | ( cd "${dir}" && tar -xf - )
+if (( PIPESTATUS[0] != 0 || PIPESTATUS[1] != 0 )); then
+    echo "Unable to tar files to ${dir}" >&2
+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).
@@ -457,14 +457,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
tar -cf - ./* | ( cd "${DIR}" && tar -xf - )
-return_codes=( "${PIPESTATUS[@]}" )
-if (( return_codes[0] != 0 )); then
-    do_something
-fi
-if (( return_codes[1] != 0 )); then
-    do_something_else
-fi
+
tar -cf - ./* | ( cd "${DIR}" && tar -xf - )
+return_codes=( "${PIPESTATUS[@]}" )
+if (( return_codes[0] != 0 )); then
+    do_something
+fi
+if (( return_codes[1] != 0 )); then
+    do_something_else
+fi
 

Use common sense and BE CONSISTENT.


diff --git a/gemfeed/2021-06-05-gemtexter-one-bash-script-to-rule-it-all.html b/gemfeed/2021-06-05-gemtexter-one-bash-script-to-rule-it-all.html index 8a4b5342..5fb41ff9 100644 --- a/gemfeed/2021-06-05-gemtexter-one-bash-script-to-rule-it-all.html +++ b/gemfeed/2021-06-05-gemtexter-one-bash-script-to-rule-it-all.html @@ -114,18 +114,18 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
paul in uranus in gemtexter on 🌱 main
-❯ wc -l gemtexter lib/*
-    117 gemtexter
-     59 lib/assert.source.sh
-    128 lib/atomfeed.source.sh
-     64 lib/gemfeed.source.sh
-    161 lib/generate.source.sh
-     50 lib/git.source.sh
-    162 lib/html.source.sh
-     30 lib/log.source.sh
-     63 lib/md.source.sh
-     834 total
+
paul in uranus in gemtexter on 🌱 main
+❯ wc -l gemtexter lib/*
+    117 gemtexter
+     59 lib/assert.source.sh
+    128 lib/atomfeed.source.sh
+     64 lib/gemfeed.source.sh
+    161 lib/generate.source.sh
+     50 lib/git.source.sh
+    162 lib/html.source.sh
+     30 lib/log.source.sh
+     63 lib/md.source.sh
+     834 total
 

This way, the script could grow far beyond 1000 lines of code and still be maintainable. With more features, execution speed may slowly become a problem, though. I already notice that Gemtexter doesn't produce results instantly but requires few seconds of runtime already. That's not a problem yet, though.
@@ -160,9 +160,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
gemtext='=> http://example.org Description of the link'
-assert::equals "$(generate::make_link html "$gemtext")" \
-    '<a class="textlink" href="http://example.org">Description of the link</a><br />'
+
gemtext='=> http://example.org Description of the link'
+assert::equals "$(generate::make_link html "$gemtext")" \
+    '<a class="textlink" href="http://example.org">Description of the link</a><br />'
 

Markdown unit test example


@@ -171,9 +171,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
gemtext='=> http://example.org Description of the link'
-assert::equals "$(generate::make_link md "$gemtext")" \
-    '[Description of the link](http://example.org)  '
+
gemtext='=> http://example.org Description of the link'
+assert::equals "$(generate::make_link md "$gemtext")" \
+    '[Description of the link](http://example.org)  '
 

Handcrafted HTML styles


diff --git a/gemfeed/2022-08-27-gemtexter-1.1.0-lets-gemtext-again.html b/gemfeed/2022-08-27-gemtexter-1.1.0-lets-gemtext-again.html index 27417834..55285faa 100644 --- a/gemfeed/2022-08-27-gemtexter-1.1.0-lets-gemtext-again.html +++ b/gemfeed/2022-08-27-gemtexter-1.1.0-lets-gemtext-again.html @@ -57,23 +57,23 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
check_dependencies () {
-    # At least, Bash 5 is required
-    local -i required_version=5
-    IFS=. read -ra version <<< "$BASH_VERSION"
-    if [ "${version[0]}" -lt $required_version ]; then
-        log ERROR "ERROR, \"bash\" must be at least at major version $required_version!"
-        exit 2
-    fi
+
check_dependencies () {
+    # At least, Bash 5 is required
+    local -i required_version=5
+    IFS=. read -ra version <<< "$BASH_VERSION"
+    if [ "${version[0]}" -lt $required_version ]; then
+        log ERROR "ERROR, \"bash\" must be at least at major version $required_version!"
+        exit 2
+    fi
 
-    # These must be the GNU versions of the commands
-    for tool in $DATE $SED $GREP; do
-        if ! $tool --version | grep -q GNU; then
-            log ERROR "ERROR, \"$tool\" command is not the GNU version, please install!"
-            exit 2
-        fi
-    done
-}
+    # These must be the GNU versions of the commands
+    for tool in $DATE $SED $GREP; do
+        if ! $tool --version | grep -q GNU; then
+            log ERROR "ERROR, \"$tool\" command is not the GNU version, please install!"
+            exit 2
+        fi
+    done
+}
 

Especially macOS users didn't read the README carefully enough to install GNU Grep, GNU Sed and GNU Date before using Gemtexter.
@@ -94,7 +94,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
./gemtexter --generate '.*hello.*'
+
./gemtexter --generate '.*hello.*'
 

Revamped git support


diff --git a/gemfeed/2022-11-24-i-tried-emacs-but-i-switched-back-to-neovim.html b/gemfeed/2022-11-24-i-tried-emacs-but-i-switched-back-to-neovim.html index 960d1845..ff921777 100644 --- a/gemfeed/2022-11-24-i-tried-emacs-but-i-switched-back-to-neovim.html +++ b/gemfeed/2022-11-24-i-tried-emacs-but-i-switched-back-to-neovim.html @@ -94,10 +94,10 @@ Art by \ \_! / __! by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
" Clipboard
-vnoremap ,y !pbcopy<CR>ugv
-vnoremap ,i !pbpaste<CR>
-nmap ,i !wpbpaste<CR>
+
" Clipboard
+vnoremap ,y !pbcopy<CR>ugv
+vnoremap ,i !pbpaste<CR>
+nmap ,i !wpbpaste<CR>
 

That's only a very few lines and does precisely what I want. It's quick and dirty but get's the job done! If VimScript becomes too cumbersome, I can use Lua for NeoVim scripting.
diff --git a/gemfeed/2023-03-25-gemtexter-2.0.0-lets-gemtext-again-2.html b/gemfeed/2023-03-25-gemtexter-2.0.0-lets-gemtext-again-2.html index eb1b2b0d..83b55016 100644 --- a/gemfeed/2023-03-25-gemtexter-2.0.0-lets-gemtext-again-2.html +++ b/gemfeed/2023-03-25-gemtexter-2.0.0-lets-gemtext-again-2.html @@ -123,8 +123,8 @@ Blablabla... by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
declare -xr PRE_GENERATE_HOOK=./pre_generate_hook.sh
-declare -xr POST_PUBLISH_HOOK=./post_publish_hook.sh
+
declare -xr PRE_GENERATE_HOOK=./pre_generate_hook.sh
+declare -xr POST_PUBLISH_HOOK=./post_publish_hook.sh
 

Use of safer Bash options


@@ -141,10 +141,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
% cat gemfeed/2023-02-26-title-here.gmi
-# Title here
+
% cat gemfeed/2023-02-26-title-here.gmi
+# Title here
 
-The remaining content of the Gemtext file...
+The remaining content of the Gemtext file...
 

Gemtexter will add a line starting with > Published at ... now. Any subsequent Atom feed generation will then use that date.
@@ -153,12 +153,12 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
% cat gemfeed/2023-02-26-title-here.gmi
-# Title here
+
% cat gemfeed/2023-02-26-title-here.gmi
+# Title here
 
-> Published at 2023-02-26T21:43:51+01:00
+> Published at 2023-02-26T21:43:51+01:00
 
-The remaining content of the Gemtext file...
+The remaining content of the Gemtext file...
 

XMLLint support


diff --git a/gemfeed/2023-05-01-unveiling-guprecords:-uptime-records-with-raku.html b/gemfeed/2023-05-01-unveiling-guprecords:-uptime-records-with-raku.html index 8308a692..4aa8ae32 100644 --- a/gemfeed/2023-05-01-unveiling-guprecords:-uptime-records-with-raku.html +++ b/gemfeed/2023-05-01-unveiling-guprecords:-uptime-records-with-raku.html @@ -77,7 +77,7 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
$ raku guprecords.raku --stats=dir=$HOME/git/uprecords/stats --all
+
$ raku guprecords.raku --stats=dir=$HOME/git/uprecords/stats --all
 

This command will generate a comprehensive uptime report from the collected statistics, making it easy to review and enjoy the data.
diff --git a/gemfeed/2023-06-01-kiss-server-monitoring-with-gogios.html b/gemfeed/2023-06-01-kiss-server-monitoring-with-gogios.html index 1b5ac65b..1e3e8701 100644 --- a/gemfeed/2023-06-01-kiss-server-monitoring-with-gogios.html +++ b/gemfeed/2023-06-01-kiss-server-monitoring-with-gogios.html @@ -117,11 +117,11 @@ Have a nice day! by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
git clone https://codeberg.org/snonux/gogios.git
-cd gogios
-go build -o gogios cmd/gogios/main.go
-doas cp gogios /usr/local/bin/gogios
-doas chmod 755 /usr/local/bin/gogios
+
git clone https://codeberg.org/snonux/gogios.git
+cd gogios
+go build -o gogios cmd/gogios/main.go
+doas cp gogios /usr/local/bin/gogios
+doas chmod 755 /usr/local/bin/gogios
 

You can use cross-compilation if you want to compile Gogios for OpenBSD on a Linux system without installing the Go compiler on OpenBSD. Follow these steps:
@@ -130,9 +130,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
export GOOS=openbsd
-export GOARCH=amd64
-go build -o gogios cmd/gogios/main.go
+
export GOOS=openbsd
+export GOARCH=amd64
+go build -o gogios cmd/gogios/main.go
 

On your OpenBSD system, copy the binary to /usr/local/bin/gogios and set the correct permissions as described in the previous section. All steps described here you could automate with your configuration management system of choice. I use Rexify, the friendly configuration management system, to automate the installation, but that is out of the scope of this document.
@@ -147,11 +147,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
doas adduser -group _gogios -batch _gogios
-doas usermod -d /var/run/gogios _gogios
-doas mkdir -p /var/run/gogios
-doas chown _gogios:_gogios /var/run/gogios
-doas chmod 750 /var/run/gogios
+
doas adduser -group _gogios -batch _gogios
+doas usermod -d /var/run/gogios _gogios
+doas mkdir -p /var/run/gogios
+doas chown _gogios:_gogios /var/run/gogios
+doas chmod 750 /var/run/gogios
 

Please note that creating a user and group might differ depending on your operating system. For other operating systems, consult their documentation for creating system users and groups.
@@ -164,8 +164,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
doas pkg_add monitoring-plugins
-doas pkg_add nrpe # If you want to execute checks remotely via NRPE.
+
doas pkg_add monitoring-plugins
+doas pkg_add nrpe # If you want to execute checks remotely via NRPE.
 

Once the installation is complete, you can find the monitoring plugins in the /usr/local/libexec/nagios directory, which then can be configured to be used in gogios.json.
@@ -192,41 +192,41 @@ echo 'This is a test email from OpenBSD.' | mail -s 'Test Email' by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
{
-  "EmailTo": "paul@dev.buetow.org",
-  "EmailFrom": "gogios@buetow.org",
-  "CheckTimeoutS": 10,
-  "CheckConcurrency": 2,
-  "StateDir": "/var/run/gogios",
-  "Checks": {
-    "Check ICMP4 www.foo.zone": {
-      "Plugin": "/usr/local/libexec/nagios/check_ping",
-      "Args": [ "-H", "www.foo.zone", "-4", "-w", "50,10%", "-c", "100,15%" ],
-      "Retries": 3,
-      "RetryInterval": 10
-    },
-    "Check ICMP6 www.foo.zone": {
-      "Plugin": "/usr/local/libexec/nagios/check_ping",
-      "Args": [ "-H", "www.foo.zone", "-6", "-w", "50,10%", "-c", "100,15%" ],
-      "Retries": 3,
-      "RetryInterval": 10
-    },
-    "www.foo.zone HTTP IPv4": {
-      "Plugin": "/usr/local/libexec/nagios/check_http",
-      "Args": ["www.foo.zone", "-4"],
-      "DependsOn": ["Check ICMP4 www.foo.zone"]
-    },
-    "www.foo.zone HTTP IPv6": {
-      "Plugin": "/usr/local/libexec/nagios/check_http",
-      "Args": ["www.foo.zone", "-6"],
-      "DependsOn": ["Check ICMP6 www.foo.zone"]
-    }
-    "Check NRPE Disk Usage foo.zone": {
-      "Plugin": "/usr/local/libexec/nagios/check_nrpe",
-      "Args": ["-H", "foo.zone", "-c", "check_disk", "-p", "5666", "-4"]
-    }
-  }
-}
+
{
+  "EmailTo": "paul@dev.buetow.org",
+  "EmailFrom": "gogios@buetow.org",
+  "CheckTimeoutS": 10,
+  "CheckConcurrency": 2,
+  "StateDir": "/var/run/gogios",
+  "Checks": {
+    "Check ICMP4 www.foo.zone": {
+      "Plugin": "/usr/local/libexec/nagios/check_ping",
+      "Args": [ "-H", "www.foo.zone", "-4", "-w", "50,10%", "-c", "100,15%" ],
+      "Retries": 3,
+      "RetryInterval": 10
+    },
+    "Check ICMP6 www.foo.zone": {
+      "Plugin": "/usr/local/libexec/nagios/check_ping",
+      "Args": [ "-H", "www.foo.zone", "-6", "-w", "50,10%", "-c", "100,15%" ],
+      "Retries": 3,
+      "RetryInterval": 10
+    },
+    "www.foo.zone HTTP IPv4": {
+      "Plugin": "/usr/local/libexec/nagios/check_http",
+      "Args": ["www.foo.zone", "-4"],
+      "DependsOn": ["Check ICMP4 www.foo.zone"]
+    },
+    "www.foo.zone HTTP IPv6": {
+      "Plugin": "/usr/local/libexec/nagios/check_http",
+      "Args": ["www.foo.zone", "-6"],
+      "DependsOn": ["Check ICMP6 www.foo.zone"]
+    }
+    "Check NRPE Disk Usage foo.zone": {
+      "Plugin": "/usr/local/libexec/nagios/check_nrpe",
+      "Args": ["-H", "foo.zone", "-c", "check_disk", "-p", "5666", "-4"]
+    }
+  }
+}
 

    @@ -255,7 +255,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    doas -u _gogios /usr/local/bin/gogios -cfg /etc/gogios.json
    +
    doas -u _gogios /usr/local/bin/gogios -cfg /etc/gogios.json
     

    To run Gogios via CRON on OpenBSD as the gogios user and check all services once per minute, follow these steps:
    diff --git a/gemfeed/2023-07-21-gemtexter-2.1.0-lets-gemtext-again-3.html b/gemfeed/2023-07-21-gemtexter-2.1.0-lets-gemtext-again-3.html index 4a38c97b..790cfebd 100644 --- a/gemfeed/2023-07-21-gemtexter-2.1.0-lets-gemtext-again-3.html +++ b/gemfeed/2023-07-21-gemtexter-2.1.0-lets-gemtext-again-3.html @@ -72,9 +72,9 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    if [ -n "$foo" ]; then
    -  echo "$foo"
    -fi
    +
    if [ -n "$foo" ]; then
    +  echo "$foo"
    +fi
     

    Please run source-highlight --lang-list for a list of all supported languages.
    @@ -103,7 +103,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    declare -xr MASTODON_URI='https://fosstodon.org/@snonux'
    +
    declare -xr MASTODON_URI='https://fosstodon.org/@snonux'
     

    and add the following into your index.gmi:
    @@ -118,7 +118,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    <a href='https://fosstodon.org/@snonux' rel='me'>Me at Mastodon</a>
    +
    <a href='https://fosstodon.org/@snonux' rel='me'>Me at Mastodon</a>
     

    More


    diff --git a/gemfeed/2023-09-25-dtail-usage-examples.html b/gemfeed/2023-09-25-dtail-usage-examples.html index bf354904..9c210fe3 100644 --- a/gemfeed/2023-09-25-dtail-usage-examples.html +++ b/gemfeed/2023-09-25-dtail-usage-examples.html @@ -70,7 +70,7 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt --grep INFO --files "/var/log/dserver/*.log"
    +
    % dtail --servers serverlist.txt --grep INFO --files "/var/log/dserver/*.log"
     

    Hint: you can also provide a comma separated server list, e.g.: servers server1.example.org,server2.example.org:PORT,...
    @@ -83,7 +83,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt --grep INFO "/var/log/dserver/*.log"
    +
    % dtail --servers serverlist.txt --grep INFO "/var/log/dserver/*.log"
     

    Aggregating logs


    @@ -96,10 +96,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt \
    -    --files '/var/log/dserver/*.log' \
    -    --query 'from STATS select sum($goroutines),sum($cgocalls),
    -             last($time),max(lifetimeConnections)'
    +
    % dtail --servers serverlist.txt \
    +    --files '/var/log/dserver/*.log' \
    +    --query 'from STATS select sum($goroutines),sum($cgocalls),
    +             last($time),max(lifetimeConnections)'
     

    Beware: For map-reduce queries to work, you have to ensure that DTail supports your log format. Check out the documentaiton of the DTail query language and the DTail log formats on the DTail homepage for more information.
    @@ -112,10 +112,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt \
    -    --files '/var/log/dserver/*.log' \
    -    'from STATS select sum($goroutines),sum($cgocalls),
    -     last($time),max(lifetimeConnections)'
    +
    % dtail --servers serverlist.txt \
    +    --files '/var/log/dserver/*.log' \
    +    'from STATS select sum($goroutines),sum($cgocalls),
    +     last($time),max(lifetimeConnections)'
     

    Here is another example:
    @@ -124,10 +124,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt \
    -    --files '/var/log/dserver/*.log' \
    -    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    -             lifetimeConnections group by $hostname order by max($cgocalls)'
    +
    % dtail --servers serverlist.txt \
    +    --files '/var/log/dserver/*.log' \
    +    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    +             lifetimeConnections group by $hostname order by max($cgocalls)'
     

    Tail map-reduce example 2
    @@ -138,9 +138,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt \
    -    --files '/var/log/dserver/*.log' \
    -    --query 'from STATS select ... outfile append result.csv'
    +
    % dtail --servers serverlist.txt \
    +    --files '/var/log/dserver/*.log' \
    +    --query 'from STATS select ... outfile append result.csv'
     

    How to use dcat


    @@ -153,7 +153,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dcat --servers serverlist.txt --files /etc/hostname
    +
    % dcat --servers serverlist.txt --files /etc/hostname
     

    Cat example
    @@ -164,7 +164,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dcat --servers serverlist.txt /etc/hostname
    +
    % dcat --servers serverlist.txt /etc/hostname
     

    How to use dgrep


    @@ -175,9 +175,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dgrep --servers server1.example.org:2223 \
    -    --files /etc/passwd \
    -    --regex nologin
    +
    % dgrep --servers server1.example.org:2223 \
    +    --files /etc/passwd \
    +    --regex nologin
     

    Generally, dgrep is also a very useful way to search historic application logs for certain content.
    @@ -194,10 +194,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dmap --servers serverlist.txt \
    -    --files '/var/log/dserver/*.log' \
    -    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    -             lifetimeConnections group by $hostname order by max($cgocalls)'
    +
    % dmap --servers serverlist.txt \
    +    --files '/var/log/dserver/*.log' \
    +    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    +             lifetimeConnections group by $hostname order by max($cgocalls)'
     

    Remember: For that to work, you have to make sure that DTail supports your log format. You can either use the ones already defined in internal/mapr/logformat or add an extension to support a custom log format. The example here works out of the box though, as DTail understands its own log format already.
    @@ -220,9 +220,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dmap --files /var/log/dserver/dserver.log
    -    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    -              lifetimeConnections group by $hostname order by max($cgocalls)'
    +
    % dmap --files /var/log/dserver/dserver.log
    +    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    +              lifetimeConnections group by $hostname order by max($cgocalls)'
     

    As a shorthand version the following command can be used:
    @@ -231,9 +231,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dmap 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    -        lifetimeConnections group by $hostname order by max($cgocalls)' \
    -        /var/log/dsever/dserver.log
    +
    % dmap 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    +        lifetimeConnections group by $hostname order by max($cgocalls)' \
    +        /var/log/dsever/dserver.log
     

    You can also use a file input pipe as follows:
    @@ -242,9 +242,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % cat /var/log/dserver/dserver.log | \
    -    dmap 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    -          lifetimeConnections group by $hostname order by max($cgocalls)'
    +
    % cat /var/log/dserver/dserver.log | \
    +    dmap 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    +          lifetimeConnections group by $hostname order by max($cgocalls)'
     

    Aggregating CSV files


    @@ -255,16 +255,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % cat example.csv
    -name,lastname,age,profession
    -Michael,Jordan,40,Basketball player
    -Michael,Jackson,100,Singer
    -Albert,Einstein,200,Physician
    -% dmap --query 'select lastname,name where age > 40 logformat csv outfile result.csv' example.csv
    -% cat result.csv
    -lastname,name
    -Jackson,Michael
    -Einstein,Albert
    +
    % cat example.csv
    +name,lastname,age,profession
    +Michael,Jordan,40,Basketball player
    +Michael,Jackson,100,Singer
    +Albert,Einstein,200,Physician
    +% dmap --query 'select lastname,name where age > 40 logformat csv outfile result.csv' example.csv
    +% cat result.csv
    +lastname,name
    +Jackson,Michael
    +Einstein,Albert
     

    DMap can also be used to query and aggregate CSV files from remote servers.
    @@ -277,44 +277,44 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail /var/log/dserver/dserver.log
    +
    % dtail /var/log/dserver/dserver.log
     

    -
    % dtail --logLevel trace /var/log/dserver/dserver.log
    +
    % dtail --logLevel trace /var/log/dserver/dserver.log
     

    -
    % dcat /etc/passwd
    +
    % dcat /etc/passwd
     

    -
    % dcat --plain /etc/passwd > /etc/test
    -# Should show no differences.
    -diff /etc/test /etc/passwd 
    +
    % dcat --plain /etc/passwd > /etc/test
    +# Should show no differences.
    +diff /etc/test /etc/passwd 
     

    -
    % dgrep --regex ERROR --files /var/log/dserver/dsever.log
    +
    % dgrep --regex ERROR --files /var/log/dserver/dsever.log
     

    -
    % dgrep --before 10 --after 10 --max 10 --grep ERROR /var/log/dserver/dsever.log
    +
    % dgrep --before 10 --after 10 --max 10 --grep ERROR /var/log/dserver/dsever.log
     

    Use --help for more available options. Or go to the DTail page for more information! Hope you find DTail useful!
    diff --git a/gemfeed/2023-10-29-kiss-static-web-photo-albums-with-photoalbum.sh.html b/gemfeed/2023-10-29-kiss-static-web-photo-albums-with-photoalbum.sh.html index 0e4cf0f0..044134e7 100644 --- a/gemfeed/2023-10-29-kiss-static-web-photo-albums-with-photoalbum.sh.html +++ b/gemfeed/2023-10-29-kiss-static-web-photo-albums-with-photoalbum.sh.html @@ -130,42 +130,42 @@ photoalbum makemake by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % photoalbum makemake
    -You may now customize ./photoalbumrc and run make
    +
    % photoalbum makemake
    +You may now customize ./photoalbumrc and run make
     
    -% cat Makefile
    -all:
    -	photoalbum generate photoalbumrc
    -clean:
    -	photoalbum clean photoalbumrc
    +% cat Makefile
    +all:
    +	photoalbum generate photoalbumrc
    +clean:
    +	photoalbum clean photoalbumrc
     
    -% cat photoalbumrc
    -# The title of the photoalbum
    -TITLE='A simple Photoalbum'
    +% cat photoalbumrc
    +# The title of the photoalbum
    +TITLE='A simple Photoalbum'
     
    -# Thumbnail height geometry
    -THUMBHEIGHT=300
    -# Normal geometry height (when viewing photo). Uncomment, to keep original size.
    -HEIGHT=1200
    -# Max previews per page.
    -MAXPREVIEWS=40
    -# Randomly shuffle all previews.
    -# SHUFFLE=yes
    +# Thumbnail height geometry
    +THUMBHEIGHT=300
    +# Normal geometry height (when viewing photo). Uncomment, to keep original size.
    +HEIGHT=1200
    +# Max previews per page.
    +MAXPREVIEWS=40
    +# Randomly shuffle all previews.
    +# SHUFFLE=yes
     
    -# Diverse directories, need to be full paths, not relative!
    -INCOMING_DIR=$(pwd)/incoming
    -DIST_DIR=$(pwd)/dist
    -TEMPLATE_DIR=/usr/share/photoalbum/templates/default
    -#TEMPLATE_DIR=/usr/share/photoalbum/templates/minimal
    +# Diverse directories, need to be full paths, not relative!
    +INCOMING_DIR=$(pwd)/incoming
    +DIST_DIR=$(pwd)/dist
    +TEMPLATE_DIR=/usr/share/photoalbum/templates/default
    +#TEMPLATE_DIR=/usr/share/photoalbum/templates/minimal
     
    -# Includes a .tar of the incoming dir in the dist, can be yes or no
    -TARBALL_INCLUDE=yes
    -TARBALL_SUFFIX=.tar
    -TAR_OPTS='-c'
    +# Includes a .tar of the incoming dir in the dist, can be yes or no
    +TARBALL_INCLUDE=yes
    +TARBALL_SUFFIX=.tar
    +TAR_OPTS='-c'
     
    -# Some debugging options
    -#set -e
    -#set -x
    +# Some debugging options
    +#set -e
    +#set -x
     

    In the case for irregular.ninja, I changed the defaults to the following:
    @@ -174,38 +174,38 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    --- photoalbumrc        2023-10-29 21:42:00.894202045 +0200
    -+++ photoalbumrc.new 2023-06-04 10:40:08.030994440 +0300
    -@@ -1,23 +1,24 @@
    - # The title of the photoalbum
    --TITLE='A simple Photoalbum'
    -+TITLE='Irregular.Ninja'
    +
    --- photoalbumrc        2023-10-29 21:42:00.894202045 +0200
    ++++ photoalbumrc.new 2023-06-04 10:40:08.030994440 +0300
    +@@ -1,23 +1,24 @@
    + # The title of the photoalbum
    +-TITLE='A simple Photoalbum'
    ++TITLE='Irregular.Ninja'
     
    - # Thumbnail height geometry
    --THUMBHEIGHT=300
    -+THUMBHEIGHT=400
    - # Normal geometry height (when viewing photo). Uncomment, to keep original size.
    --HEIGHT=1200
    -+HEIGHT=1800
    - # Max previews per page.
    - MAXPREVIEWS=40
    --# Randomly shuffle all previews.
    --# SHUFFLE=yes
    -+# Randomly shuffle
    -+SHUFFLE=yes
    + # Thumbnail height geometry
    +-THUMBHEIGHT=300
    ++THUMBHEIGHT=400
    + # Normal geometry height (when viewing photo). Uncomment, to keep original size.
    +-HEIGHT=1200
    ++HEIGHT=1800
    + # Max previews per page.
    + MAXPREVIEWS=40
    +-# Randomly shuffle all previews.
    +-# SHUFFLE=yes
    ++# Randomly shuffle
    ++SHUFFLE=yes
     
    - # Diverse directories, need to be full paths, not relative!
    --INCOMING_DIR=$(pwd)/incoming
    -+INCOMING_DIR=~/Nextcloud/Photos/irregular.ninja
    - DIST_DIR=$(pwd)/dist
    - TEMPLATE_DIR=/usr/share/photoalbum/templates/default
    - #TEMPLATE_DIR=/usr/share/photoalbum/templates/minimal
    + # Diverse directories, need to be full paths, not relative!
    +-INCOMING_DIR=$(pwd)/incoming
    ++INCOMING_DIR=~/Nextcloud/Photos/irregular.ninja
    + DIST_DIR=$(pwd)/dist
    + TEMPLATE_DIR=/usr/share/photoalbum/templates/default
    + #TEMPLATE_DIR=/usr/share/photoalbum/templates/minimal
     
    - # Includes a .tar of the incoming dir in the dist, can be yes or no
    --TARBALL_INCLUDE=yes
    -+TARBALL_INCLUDE=no
    - TARBALL_SUFFIX=.tar
    - TAR_OPTS='-c'
    + # Includes a .tar of the incoming dir in the dist, can be yes or no
    +-TARBALL_INCLUDE=yes
    ++TARBALL_INCLUDE=no
    + TARBALL_SUFFIX=.tar
    + TAR_OPTS='-c'
     

    So I changed the album title, adjusted some image and thumbnail dimensions, and I want all images to be randomly shuffled every time the album is generated! I also have all my photos in my Nextcloud Photo directory and don't want to copy them to the local incoming directory. Also, a tarball containing the whole album as a download isn't provided.
    diff --git a/gemfeed/2023-12-10-bash-golf-part-3.html b/gemfeed/2023-12-10-bash-golf-part-3.html index 538806b6..08801198 100644 --- a/gemfeed/2023-12-10-bash-golf-part-3.html +++ b/gemfeed/2023-12-10-bash-golf-part-3.html @@ -55,24 +55,24 @@ jgs^^^^^^^`^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -log () {
    -    local -r level="$1"; shift
    -    local -r message="$1"; shift
    -    local -i pid="$$"
    +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)
    +    local -r callee=${FUNCNAME[1]}
    +    local -r stamp=$(date +%Y%m%d-%H%M%S)
     
    -    echo "$level|$stamp|$pid|$callee|$message" >&2
    -}
    +    echo "$level|$stamp|$pid|$callee|$message" >&2
    +}
     
    -at_home_friday_evening () {
    -    log INFO 'One Peperoni Pizza, please'
    -}
    +at_home_friday_evening () {
    +    log INFO 'One Peperoni Pizza, please'
    +}
     
    -at_home_friday_evening
    +at_home_friday_evening
     

    The output is as follows:
    @@ -81,8 +81,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ./logexample.sh
    -INFO|20231210-082732|123002|at_home_friday_evening|One Peperoni Pizza, please
    +
    ./logexample.sh
    +INFO|20231210-082732|123002|at_home_friday_evening|One Peperoni Pizza, please
     

    :(){ :|:& };:


    @@ -116,18 +116,18 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    -
    -outer() {
    -  inner() {
    -    echo 'Intel inside!'
    -  }
    -  inner
    -}
    -
    -inner
    -outer
    -inner
    +
    #!/usr/bin/env bash
    +
    +outer() {
    +  inner() {
    +    echo 'Intel inside!'
    +  }
    +  inner
    +}
    +
    +inner
    +outer
    +inner
     

    And let's execute it:
    @@ -145,26 +145,26 @@ Intel inside! by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    -
    -outer1() {
    -  inner() {
    -    echo 'Intel inside!'
    -  }
    -  inner
    -}
    -
    -outer2() {
    -  inner() {
    -    echo 'Wintel inside!'
    -  }
    -  inner
    -}
    -
    -outer1
    -inner
    -outer2
    -inner
    +
    #!/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:
    @@ -185,14 +185,14 @@ Wintel inside! by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -some_expensive_operations() {
    -  echo "Doing expensive operations with '$1' from pid $$"
    -}
    +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 "{}"'
    +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:
    @@ -217,15 +217,15 @@ bash: line 1: some_expensive_operations: command not found by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -some_expensive_operations() {
    -  echo "Doing expensive operations with '$1' from pid $$"
    -}
    -export -f some_expensive_operations
    +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 "{}"'
    +for i in {0..9}; do echo $i; done \
    +  | xargs -P10 -I{} bash -c 'some_expensive_operations "{}"'
     

    When we run this now, we get:
    @@ -250,19 +250,19 @@ Doing expensive operations with '9' from pid 132840 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -some_other_function() {
    -  echo "$1"
    -}
    +some_other_function() {
    +  echo "$1"
    +}
     
    -some_expensive_operations() {
    -  some_other_function "Doing expensive operations with '$1' from pid $$"
    -}
    -export -f some_expensive_operations
    +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 "{}"'
    +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!
    @@ -275,22 +275,22 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/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"
    +
    #!/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?
    @@ -315,34 +315,34 @@ foo by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -declare -r foo=foo
    -declare -r bar=bar
    +declare -r foo=foo
    +declare -r bar=bar
     
    -if [ "$foo" = foo ]; then
    -  if [ "$bar" = bar ]; then
    -    echo ok1
    -  fi
    -fi
    +if [ "$foo" = foo ]; then
    +  if [ "$bar" = bar ]; then
    +    echo ok1
    +  fi
    +fi
     
    -if [ "$foo" = foo ] && [ "$bar" == bar ]; then
    -  echo ok2a
    -fi
    +if [ "$foo" = foo ] && [ "$bar" == bar ]; then
    +  echo ok2a
    +fi
     
    -[ "$foo" = foo ] && [ "$bar" == bar ] && echo ok2b
    +[ "$foo" = foo ] && [ "$bar" == bar ] && echo ok2b
     
    -if [[ "$foo" = foo && "$bar" == bar ]]; then
    -  echo ok3a
    -fi
    +if [[ "$foo" = foo && "$bar" == bar ]]; then
    +  echo ok3a
    +fi
     
    - [[ "$foo" = foo && "$bar" == bar ]] && echo ok3b
    + [[ "$foo" = foo && "$bar" == bar ]] && echo ok3b
     
    -if test "$foo" = foo && test "$bar" = bar; then
    -  echo ok4a
    -fi
    +if test "$foo" = foo && test "$bar" = bar; then
    +  echo ok4a
    +fi
     
    -test "$foo" = foo && test "$bar" = bar && echo ok4b
    +test "$foo" = foo && test "$bar" = bar && echo ok4b
     

    The output we get is:
    @@ -366,18 +366,18 @@ ok4b by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -# Single line comment
    +# Single line comment
     
    -# These are two single line
    -# comments one after another
    +# These are two single line
    +# comments one after another
     
    -: <<COMMENT
    -This is another way a
    -multi line comment
    -could be written!
    -COMMENT
    +: <<COMMENT
    +This is another way a
    +multi line comment
    +could be written!
    +COMMENT
     

    I will not demonstrate the execution of this script, as it won't print anything! It's obviously not the most pretty way of commenting on your code, but it could sometimes be handy!
    @@ -390,11 +390,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -echo foo
    -echo echo baz >> $0
    -echo bar
    +echo foo
    +echo echo baz >> $0
    +echo bar
     

    When it is run, it will do:
    diff --git a/gemfeed/2024-01-13-one-reason-why-i-love-openbsd.html b/gemfeed/2024-01-13-one-reason-why-i-love-openbsd.html index bd4584b1..8a05e22a 100644 --- a/gemfeed/2024-01-13-one-reason-why-i-love-openbsd.html +++ b/gemfeed/2024-01-13-one-reason-why-i-love-openbsd.html @@ -39,8 +39,8 @@ SSFISHKISSFISHKISSFISHKISSFISHKIS SFIS by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    $ doas installboot sd0 # Update the bootloader (not for every upgrade required)
    -$ doas sysupgrade # Update all binaries (including Kernel)
    +
    $ doas installboot sd0 # Update the bootloader (not for every upgrade required)
    +$ doas sysupgrade # Update all binaries (including Kernel)
     

    sysupgrade downloaded and upgraded to the next release and rebooted the system. After the reboot, I run:
    @@ -49,9 +49,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    $ doas sysmerge # Update system configuration files
    -$ doas pkg_add -u # Update all packages
    -$ doas reboot # Just in case, reboot one more time
    +
    $ doas sysmerge # Update system configuration files
    +$ doas pkg_add -u # Update all packages
    +$ doas reboot # Just in case, reboot one more time
     

    That's it! Took me around 5 minutes in total! No issues, only these few comands, only 5 minutes! It just works! No problems, no conflicts, no tons (actually none) config file merge conflicts.
    diff --git a/gemfeed/2024-04-01-KISS-high-availability-with-OpenBSD.html b/gemfeed/2024-04-01-KISS-high-availability-with-OpenBSD.html index 18be2c59..a32c2689 100644 --- a/gemfeed/2024-04-01-KISS-high-availability-with-OpenBSD.html +++ b/gemfeed/2024-04-01-KISS-high-availability-with-OpenBSD.html @@ -98,38 +98,38 @@ _____|_:_:_| (o)-(o) |_:_:_|--'`-. ,--. ksh under-water (((\'/ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/bin/ksh
    +
    #!/bin/ksh
     
    -ZONES_DIR=/var/nsd/zones/master/
    -DEFAULT_MASTER=fishfinger.buetow.org
    -DEFAULT_STANDBY=blowfish.buetow.org
    +ZONES_DIR=/var/nsd/zones/master/
    +DEFAULT_MASTER=fishfinger.buetow.org
    +DEFAULT_STANDBY=blowfish.buetow.org
     
    -determine_master_and_standby () {
    -    local master=$DEFAULT_MASTER
    -    local standby=$DEFAULT_STANDBY
    +determine_master_and_standby () {
    +    local master=$DEFAULT_MASTER
    +    local standby=$DEFAULT_STANDBY
     
    -    .
    -    .
    -    .
    -    
    -    local -i health_ok=1
    -    if ! ftp -4 -o - https://$master/index.txt | grep -q "Welcome to $master"; then
    -        echo "https://$master/index.txt IPv4 health check failed"
    -        health_ok=0
    -    elif ! ftp -6 -o - https://$master/index.txt | grep -q "Welcome to $master"; then
    -        echo "https://$master/index.txt IPv6 health check failed"
    -        health_ok=0
    -    fi
    -    if [ $health_ok -eq 0 ]; then
    -        local tmp=$master
    -        master=$standby
    -        standby=$tmp
    -    fi
    +    .
    +    .
    +    .
    +    
    +    local -i health_ok=1
    +    if ! ftp -4 -o - https://$master/index.txt | grep -q "Welcome to $master"; then
    +        echo "https://$master/index.txt IPv4 health check failed"
    +        health_ok=0
    +    elif ! ftp -6 -o - https://$master/index.txt | grep -q "Welcome to $master"; then
    +        echo "https://$master/index.txt IPv6 health check failed"
    +        health_ok=0
    +    fi
    +    if [ $health_ok -eq 0 ]; then
    +        local tmp=$master
    +        master=$standby
    +        standby=$tmp
    +    fi
     
    -    .
    -    .
    -    .
    -}
    +    .
    +    .
    +    .
    +}
     

    The failover scripts looks for the ; Enable failover string in the DNS zone files and swaps the A and AAAA records of the DNS entries accordingly:
    @@ -138,42 +138,42 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    fishfinger$ grep failover /var/nsd/zones/master/foo.zone.zone
    -        300 IN A 46.23.94.99 ; Enable failover
    -        300 IN AAAA 2a03:6000:6f67:624::99 ; Enable failover
    -www     300 IN A 46.23.94.99 ; Enable failover
    -www     300 IN AAAA 2a03:6000:6f67:624::99 ; Enable failover
    -standby  300 IN A 23.88.35.144 ; Enable failover
    -standby  300 IN AAAA 2a01:4f8:c17:20f1::42 ; Enable failover
    +
    fishfinger$ grep failover /var/nsd/zones/master/foo.zone.zone
    +        300 IN A 46.23.94.99 ; Enable failover
    +        300 IN AAAA 2a03:6000:6f67:624::99 ; Enable failover
    +www     300 IN A 46.23.94.99 ; Enable failover
    +www     300 IN AAAA 2a03:6000:6f67:624::99 ; Enable failover
    +standby  300 IN A 23.88.35.144 ; Enable failover
    +standby  300 IN AAAA 2a01:4f8:c17:20f1::42 ; Enable failover
     

    -
    transform () {
    -  sed -E '
    -	/IN A .*; Enable failover/ {
    -	    /^standby/! {
    -	        s/^(.*) 300 IN A (.*) ; (.*)/\1 300 IN A '$(cat /var/nsd/run/master_a)' ; \3/;
    -	    }
    -	    /^standby/ {
    -	        s/^(.*) 300 IN A (.*) ; (.*)/\1 300 IN A '$(cat /var/nsd/run/standby_a)' ; \3/;
    -	    }
    -	}
    -	/IN AAAA .*; Enable failover/ {
    -	    /^standby/! {
    -	        s/^(.*) 300 IN AAAA (.*) ; (.*)/\1 300 IN AAAA '$(cat /var/nsd/run/master_aaaa)' ; \3/;
    -	    }
    -	    /^standby/ {
    -	        s/^(.*) 300 IN AAAA (.*) ; (.*)/\1 300 IN AAAA '$(cat /var/nsd/run/standby_aaaa)' ; \3/;
    -	    }
    -	}
    -	/ ; serial/ {
    -	    s/^( +) ([0-9]+) .*; (.*)/\1 '$(date +%s)' ; \3/;
    -	}
    -  '
    -}
    +
    transform () {
    +  sed -E '
    +	/IN A .*; Enable failover/ {
    +	    /^standby/! {
    +	        s/^(.*) 300 IN A (.*) ; (.*)/\1 300 IN A '$(cat /var/nsd/run/master_a)' ; \3/;
    +	    }
    +	    /^standby/ {
    +	        s/^(.*) 300 IN A (.*) ; (.*)/\1 300 IN A '$(cat /var/nsd/run/standby_a)' ; \3/;
    +	    }
    +	}
    +	/IN AAAA .*; Enable failover/ {
    +	    /^standby/! {
    +	        s/^(.*) 300 IN AAAA (.*) ; (.*)/\1 300 IN AAAA '$(cat /var/nsd/run/master_aaaa)' ; \3/;
    +	    }
    +	    /^standby/ {
    +	        s/^(.*) 300 IN AAAA (.*) ; (.*)/\1 300 IN AAAA '$(cat /var/nsd/run/standby_aaaa)' ; \3/;
    +	    }
    +	}
    +	/ ; serial/ {
    +	    s/^( +) ([0-9]+) .*; (.*)/\1 '$(date +%s)' ; \3/;
    +	}
    +  '
    +}
     

    After the failover, the script reloads nsd and performs a sanity check to see if DNS still works. If not, a rollback will be performed:
    @@ -182,48 +182,48 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #! Race condition !#
    -   
    -if [ -f $zone_file.bak ]; then
    -    mv $zone_file.bak $zone_file
    -fi
    +
    #! Race condition !#
    +   
    +if [ -f $zone_file.bak ]; then
    +    mv $zone_file.bak $zone_file
    +fi
     
    -cat $zone_file | transform > $zone_file.new.tmp 
    +cat $zone_file | transform > $zone_file.new.tmp 
     
    -grep -v ' ; serial' $zone_file.new.tmp > $zone_file.new.noserial.tmp
    -grep -v ' ; serial' $zone_file > $zone_file.old.noserial.tmp
    +grep -v ' ; serial' $zone_file.new.tmp > $zone_file.new.noserial.tmp
    +grep -v ' ; serial' $zone_file > $zone_file.old.noserial.tmp
     
    -echo "Has zone $zone_file changed?"
    -if diff -u $zone_file.old.noserial.tmp $zone_file.new.noserial.tmp; then
    -    echo "The zone $zone_file hasn't changed"
    -    rm $zone_file.*.tmp
    -    return 0
    -fi
    +echo "Has zone $zone_file changed?"
    +if diff -u $zone_file.old.noserial.tmp $zone_file.new.noserial.tmp; then
    +    echo "The zone $zone_file hasn't changed"
    +    rm $zone_file.*.tmp
    +    return 0
    +fi
     
    -cp $zone_file $zone_file.bak
    -mv $zone_file.new.tmp $zone_file
    -rm $zone_file.*.tmp
    -echo "Reloading nsd"
    -nsd-control reload
    +cp $zone_file $zone_file.bak
    +mv $zone_file.new.tmp $zone_file
    +rm $zone_file.*.tmp
    +echo "Reloading nsd"
    +nsd-control reload
     
    -if ! zone_is_ok $zone; then
    -    echo "Rolling back $zone_file changes"
    -    cp $zone_file $zone_file.invalid
    -    mv $zone_file.bak $zone_file
    -    echo "Reloading nsd"
    -    nsd-control reload
    -    zone_is_ok $zone
    -    return 3
    -fi
    +if ! zone_is_ok $zone; then
    +    echo "Rolling back $zone_file changes"
    +    cp $zone_file $zone_file.invalid
    +    mv $zone_file.bak $zone_file
    +    echo "Reloading nsd"
    +    nsd-control reload
    +    zone_is_ok $zone
    +    return 3
    +fi
     
    -for cleanup in invalid bak; do
    -    if [ -f $zone_file.$cleanup ]; then
    -        rm $zone_file.$cleanup
    -    fi
    -done
    +for cleanup in invalid bak; do
    +    if [ -f $zone_file.$cleanup ]; then
    +        rm $zone_file.$cleanup
    +    fi
    +done
     
    -echo "Failover of zone $zone to $MASTER completed"
    -return 1
    +echo "Failover of zone $zone to $MASTER completed"
    +return 1
     

    A non-zero return code (here, 3 when a rollback and 1 when a DNS failover was performed) will cause CRON to send an E-Mail with the whole script output.
    @@ -280,13 +280,13 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    # Weekly auto-failover for Let's Encrypt automation
    -local -i -r week_of_the_year=$(date +%U)
    -if [ $(( week_of_the_year % 2 )) -eq 0 ]; then
    -    local tmp=$master
    -    master=$standby
    -    standby=$tmp
    -fi
    +
    # Weekly auto-failover for Let's Encrypt automation
    +local -i -r week_of_the_year=$(date +%U)
    +if [ $(( week_of_the_year % 2 )) -eq 0 ]; then
    +    local tmp=$master
    +    master=$standby
    +    standby=$tmp
    +fi
     

    This way, a DNS failover is performed weekly so that the ACME automation can update the Let's Encrypt certificates (for master and standby) before they expire on each VM.
    diff --git a/gemfeed/2024-05-03-projects-i-currently-dont-have-time-for.html b/gemfeed/2024-05-03-projects-i-currently-dont-have-time-for.html index 3cc4bc40..ba1cb4b2 100644 --- a/gemfeed/2024-05-03-projects-i-currently-dont-have-time-for.html +++ b/gemfeed/2024-05-03-projects-i-currently-dont-have-time-for.html @@ -220,12 +220,12 @@ Art by Laura Brown by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    Cluster :UK, :uk01 do
    -  Customer.C1A1.segments.volumes.each do |volume|
    -    puts volume.usage_stats
    -    volume.move_off! if volume.over_subscribed?
    -  end
    -end
    +
    Cluster :UK, :uk01 do
    +  Customer.C1A1.segments.volumes.each do |volume|
    +    puts volume.usage_stats
    +    volume.move_off! if volume.over_subscribed?
    +  end
    +end
     

    I am abandoning this project because my workplace has stopped the annual pet project competition, and I have other more important projects to work on at the moment.
    diff --git a/gemfeed/2024-06-23-terminal-multiplexing-with-tmux.html b/gemfeed/2024-06-23-terminal-multiplexing-with-tmux.html index d2050ad0..c284fd57 100644 --- a/gemfeed/2024-06-23-terminal-multiplexing-with-tmux.html +++ b/gemfeed/2024-06-23-terminal-multiplexing-with-tmux.html @@ -90,13 +90,13 @@ jgs `-=========-`() by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    alias tm=tmux
    -alias tl='tmux list-sessions'
    -alias tn=tmux::new
    -alias ta=tmux::attach
    -alias tx=tmux::remote
    -alias ts=tmux::search
    -alias tssh=tmux::cluster_ssh
    +
    alias tm=tmux
    +alias tl='tmux list-sessions'
    +alias tn=tmux::new
    +alias ta=tmux::attach
    +alias tx=tmux::remote
    +alias ts=tmux::search
    +alias tssh=tmux::cluster_ssh
     

    Note all tmux::...; those are custom shell functions doing certain things, and they aren't part of the Tmux distribution. But let's run through every aliases one by one.
    @@ -111,23 +111,23 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    # Create new session and if alread exists attach to it
    -tmux::new () {
    -    readonly session=$1
    -    local date=date
    -    if where gdate &>/dev/null; then
    -        date=gdate
    -    fi
    +
    # Create new session and if alread exists attach to it
    +tmux::new () {
    +    readonly session=$1
    +    local date=date
    +    if where gdate &>/dev/null; then
    +        date=gdate
    +    fi
     
    -    tmux::cleanup_default
    -    if [ -z "$session" ]; then
    -        tmux::new T$($date +%s)
    -    else
    -        tmux new-session -d -s $session
    -        tmux -2 attach-session -t $session || tmux -2 switch-client -t $session
    -    fi
    -}
    -alias tn=tmux::new
    +    tmux::cleanup_default
    +    if [ -z "$session" ]; then
    +        tmux::new T$($date +%s)
    +    else
    +        tmux new-session -d -s $session
    +        tmux -2 attach-session -t $session || tmux -2 switch-client -t $session
    +    fi
    +}
    +alias tn=tmux::new
     

    There is a lot going on here. Let's have a detailed look at what it is doing. As a note, the function relies on GNU Date, so MacOS is looking for the gdate commands to be available. Otherwise, it will fall back to date. You need to install GNU Date for Mac, as it isn't installed by default there. As I use Fedora Linux on my personal Laptop and a MacBook for work, I have to make it work for both.
    @@ -142,14 +142,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::cleanup_default () {
    -    local s
    -    tmux list-sessions | grep '^T.*: ' | grep -F -v attached |
    -    cut -d: -f1 | while read -r s; do
    -        echo "Killing $s"
    -        tmux kill-session -t "$s"
    -    done
    -}
    +
    tmux::cleanup_default () {
    +    local s
    +    tmux list-sessions | grep '^T.*: ' | grep -F -v attached |
    +    cut -d: -f1 | while read -r s; do
    +        echo "Killing $s"
    +        tmux kill-session -t "$s"
    +    done
    +}
     

    The cleanup function kills all open Tmux sessions that haven't been renamed properly yet—but only if they aren't attached (e.g., don't run in the foreground in any terminal). Cleaning them up automatically keeps my Tmux sessions as neat and tidy as possible.
    @@ -166,16 +166,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::attach () {
    -    readonly session=$1
    +
    tmux::attach () {
    +    readonly session=$1
     
    -    if [ -z "$session" ]; then
    -        tmux attach-session || tmux::new
    -    else
    -        tmux attach-session -t $session || tmux::new $session
    -    fi
    -}
    -alias ta=tmux::attach
    +    if [ -z "$session" ]; then
    +        tmux attach-session || tmux::new
    +    else
    +        tmux attach-session -t $session || tmux::new $session
    +    fi
    +}
    +alias ta=tmux::attach
     

    If no session is specified (as the argument of the function), it will try to attach to the first open session. If no Tmux server is running, it will create a new one with tmux::new. Otherwise, with a session name given as the argument, it will attach to it. If unsuccessful (e.g., the session doesn't exist), it will be created and attached to.
    @@ -188,12 +188,12 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::remote () {
    -    readonly server=$1
    -    tmux new -s $server "ssh -t $server 'tmux attach-session || tmux'" || \
    -        tmux attach-session -d -t $server
    -}
    -alias tr=tmux::remote
    +
    tmux::remote () {
    +    readonly server=$1
    +    tmux new -s $server "ssh -t $server 'tmux attach-session || tmux'" || \
    +        tmux attach-session -d -t $server
    +}
    +alias tr=tmux::remote
     

    Change of the Tmux prefix for better nesting


    @@ -216,15 +216,15 @@ set-option -g prefix C-g by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::search () {
    -    local -r session=$(tmux list-sessions | fzf | cut -d: -f1)
    -    if [ -z "$TMUX" ]; then
    -        tmux attach-session -t $session
    -    else
    -        tmux switch -t $session
    -    fi
    -}
    -alias ts=tmux::search
    +
    tmux::search () {
    +    local -r session=$(tmux list-sessions | fzf | cut -d: -f1)
    +    if [ -z "$TMUX" ]; then
    +        tmux attach-session -t $session
    +    else
    +        tmux switch -t $session
    +    fi
    +}
    +alias ts=tmux::search
     

    All it does is list all currently open sessions in fzf, where one of them can be searched and selected through fuzzy find, and then either switch (if already inside a session) to the other session or attach to the other session (if not yet in Tmux).
    @@ -251,15 +251,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::cluster_ssh () {
    -    if [ -f "$1" ]; then
    -        tmux::tssh_from_file $1
    -        return
    -    fi
    +
    tmux::cluster_ssh () {
    +    if [ -f "$1" ]; then
    +        tmux::tssh_from_file $1
    +        return
    +    fi
     
    -    tmux::tssh_from_argument $@
    -}
    -alias tssh=tmux::cluster_ssh
    +    tmux::tssh_from_argument $@
    +}
    +alias tssh=tmux::cluster_ssh
     

    This function is just a wrapper around the more complex tmux::tssh_from_file and tmux::tssh_from_argument functions, as you have learned already. Most of the magic happens there.
    @@ -272,23 +272,23 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::tssh_from_argument () {
    -    local -r session=$1; shift
    -    local first_server=$1; shift
    +
    tmux::tssh_from_argument () {
    +    local -r session=$1; shift
    +    local first_server=$1; shift
     
    -    tmux new-session -d -s $session "ssh -t $first_server"
    -    if ! tmux list-session | grep "^$session:"; then
    -        echo "Could not create session $session"
    -        return 2
    -    fi
    +    tmux new-session -d -s $session "ssh -t $first_server"
    +    if ! tmux list-session | grep "^$session:"; then
    +        echo "Could not create session $session"
    +        return 2
    +    fi
     
    -    for server in "${@[@]}"; do
    -        tmux split-window -t $session "tmux select-layout tiled; ssh -t $server"
    -    done
    +    for server in "${@[@]}"; do
    +        tmux split-window -t $session "tmux select-layout tiled; ssh -t $server"
    +    done
     
    -    tmux setw -t $session synchronize-panes on
    -    tmux -2 attach-session -t $session | tmux -2 switch-client -t $session
    -}
    +    tmux setw -t $session synchronize-panes on
    +    tmux -2 attach-session -t $session | tmux -2 switch-client -t $session
    +}
     

    It expects at least two arguments. The first argument is the session name to create for the clustered SSH session. All other arguments are server hostnames or FQDNs to which to connect. The first one is used to make the initial session. All remaining ones are added to that session with tmux split-window -t $session.... At the end, we enable synchronized panes by default, so whenever you type, the commands will be sent to every SSH connection, thus allowing the neat ClusterSSH feature to run commands on multiple servers simultaneously. Once done, we attach (or switch, if already in Tmux) to it.
    @@ -308,12 +308,12 @@ bind-key P setw synchronize-panes on by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::tssh_from_file () {
    -    local -r serverlist=$1; shift
    -    local -r session=$(basename $serverlist | cut -d. -f1)
    +
    tmux::tssh_from_file () {
    +    local -r serverlist=$1; shift
    +    local -r session=$(basename $serverlist | cut -d. -f1)
     
    -    tmux::tssh_from_argument $session $(awk '{ print $1} ' $serverlist | sed 's/.lan./.lan/g')
    -}
    +    tmux::tssh_from_argument $session $(awk '{ print $1} ' $serverlist | sed 's/.lan./.lan/g')
    +}
     

    tssh examples


    diff --git a/gemfeed/2024-07-05-random-weird-things.html b/gemfeed/2024-07-05-random-weird-things.html index 58f284ec..7f92d609 100644 --- a/gemfeed/2024-07-05-random-weird-things.html +++ b/gemfeed/2024-07-05-random-weird-things.html @@ -55,52 +55,52 @@ WHOA!! ( o.o ) by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ❯ traceroute -m 60 bad.horse
    -traceroute to bad.horse (162.252.205.157), 60 hops max, 60 byte packets
    - 1  _gateway (192.168.1.1)  5.237 ms  5.264 ms  6.009 ms
    - 2  77-85-0-2.ip.btc-net.bg (77.85.0.2)  8.753 ms  7.112 ms  8.336 ms
    - 3  212-39-69-103.ip.btc-net.bg (212.39.69.103)  9.434 ms  9.268 ms  9.986 ms
    - 4  * * *
    - 5  xe-1-2-0.mpr1.fra4.de.above.net (80.81.194.26)  39.812 ms  39.030 ms  39.772 ms
    - 6  * ae12.cs1.fra6.de.eth.zayo.com (64.125.26.172)  123.576 ms *
    - 7  * * *
    - 8  * * *
    - 9  ae10.cr1.lhr15.uk.eth.zayo.com (64.125.29.17)  119.097 ms  119.478 ms  120.767 ms
    -10  ae2.cr1.lhr11.uk.zip.zayo.com (64.125.24.140)  120.398 ms  121.147 ms  120.948 ms
    -11  * * *
    -12  ae25.mpr1.yyz1.ca.zip.zayo.com (64.125.23.117)  145.072 ms *  181.773 ms
    -13  ae5.mpr1.tor3.ca.zip.zayo.com (64.125.23.118)  168.239 ms  168.158 ms  168.137 ms
    -14  64.124.217.237.IDIA-265104-ZYO.zip.zayo.com (64.124.217.237)  168.026 ms  167.999 ms  165.451 ms
    -15  * * *
    -16  t00.toroc1.on.ca.sn11.net (162.252.204.2)  131.598 ms  131.308 ms  131.482 ms
    -17  bad.horse (162.252.205.130)  131.430 ms  145.914 ms  130.514 ms
    -18  bad.horse (162.252.205.131)  136.634 ms  145.295 ms  135.631 ms
    -19  bad.horse (162.252.205.132)  139.158 ms  148.363 ms  138.934 ms
    -20  bad.horse (162.252.205.133)  145.395 ms  148.054 ms  147.140 ms
    -21  he.rides.across.the.nation (162.252.205.134)  149.687 ms  147.731 ms  150.135 ms
    -22  the.thoroughbred.of.sin (162.252.205.135)  156.644 ms  155.155 ms  156.447 ms
    -23  he.got.the.application (162.252.205.136)  161.187 ms  162.318 ms  162.674 ms
    -24  that.you.just.sent.in (162.252.205.137)  166.763 ms  166.675 ms  164.243 ms
    -25  it.needs.evaluation (162.252.205.138)  172.073 ms  171.919 ms  171.390 ms
    -26  so.let.the.games.begin (162.252.205.139)  175.386 ms  174.180 ms  175.965 ms
    -27  a.heinous.crime (162.252.205.140)  180.857 ms  180.766 ms  180.192 ms
    -28  a.show.of.force (162.252.205.141)  187.942 ms  186.669 ms  186.986 ms
    -29  a.murder.would.be.nice.of.course (162.252.205.142)  191.349 ms  191.939 ms  190.740 ms
    -30  bad.horse (162.252.205.143)  195.425 ms  195.716 ms  196.186 ms
    -31  bad.horse (162.252.205.144)  199.238 ms  200.620 ms  200.318 ms
    -32  bad.horse (162.252.205.145)  207.554 ms  206.729 ms  205.201 ms
    -33  he-s.bad (162.252.205.146)  211.087 ms  211.649 ms  211.712 ms
    -34  the.evil.league.of.evil (162.252.205.147)  212.657 ms  216.777 ms  216.589 ms
    -35  is.watching.so.beware (162.252.205.148)  220.911 ms  220.326 ms  221.961 ms
    -36  the.grade.that.you.receive (162.252.205.149)  225.384 ms  225.696 ms  225.640 ms
    -37  will.be.your.last.we.swear (162.252.205.150)  232.312 ms  230.989 ms  230.919 ms
    -38  so.make.the.bad.horse.gleeful (162.252.205.151)  235.761 ms  235.291 ms  235.585 ms
    -39  or.he-ll.make.you.his.mare (162.252.205.152)  241.350 ms  239.407 ms  238.394 ms
    -40  o_o (162.252.205.153)  246.154 ms  247.650 ms  247.110 ms
    -41  you-re.saddled.up (162.252.205.154)  250.925 ms  250.401 ms  250.619 ms
    -42  there-s.no.recourse (162.252.205.155)  256.071 ms  251.154 ms  255.340 ms
    -43  it-s.hi-ho.silver (162.252.205.156)  260.152 ms  261.775 ms  261.544 ms
    -44  signed.bad.horse (162.252.205.157)  262.430 ms  261.410 ms  261.365 ms
    +
    ❯ traceroute -m 60 bad.horse
    +traceroute to bad.horse (162.252.205.157), 60 hops max, 60 byte packets
    + 1  _gateway (192.168.1.1)  5.237 ms  5.264 ms  6.009 ms
    + 2  77-85-0-2.ip.btc-net.bg (77.85.0.2)  8.753 ms  7.112 ms  8.336 ms
    + 3  212-39-69-103.ip.btc-net.bg (212.39.69.103)  9.434 ms  9.268 ms  9.986 ms
    + 4  * * *
    + 5  xe-1-2-0.mpr1.fra4.de.above.net (80.81.194.26)  39.812 ms  39.030 ms  39.772 ms
    + 6  * ae12.cs1.fra6.de.eth.zayo.com (64.125.26.172)  123.576 ms *
    + 7  * * *
    + 8  * * *
    + 9  ae10.cr1.lhr15.uk.eth.zayo.com (64.125.29.17)  119.097 ms  119.478 ms  120.767 ms
    +10  ae2.cr1.lhr11.uk.zip.zayo.com (64.125.24.140)  120.398 ms  121.147 ms  120.948 ms
    +11  * * *
    +12  ae25.mpr1.yyz1.ca.zip.zayo.com (64.125.23.117)  145.072 ms *  181.773 ms
    +13  ae5.mpr1.tor3.ca.zip.zayo.com (64.125.23.118)  168.239 ms  168.158 ms  168.137 ms
    +14  64.124.217.237.IDIA-265104-ZYO.zip.zayo.com (64.124.217.237)  168.026 ms  167.999 ms  165.451 ms
    +15  * * *
    +16  t00.toroc1.on.ca.sn11.net (162.252.204.2)  131.598 ms  131.308 ms  131.482 ms
    +17  bad.horse (162.252.205.130)  131.430 ms  145.914 ms  130.514 ms
    +18  bad.horse (162.252.205.131)  136.634 ms  145.295 ms  135.631 ms
    +19  bad.horse (162.252.205.132)  139.158 ms  148.363 ms  138.934 ms
    +20  bad.horse (162.252.205.133)  145.395 ms  148.054 ms  147.140 ms
    +21  he.rides.across.the.nation (162.252.205.134)  149.687 ms  147.731 ms  150.135 ms
    +22  the.thoroughbred.of.sin (162.252.205.135)  156.644 ms  155.155 ms  156.447 ms
    +23  he.got.the.application (162.252.205.136)  161.187 ms  162.318 ms  162.674 ms
    +24  that.you.just.sent.in (162.252.205.137)  166.763 ms  166.675 ms  164.243 ms
    +25  it.needs.evaluation (162.252.205.138)  172.073 ms  171.919 ms  171.390 ms
    +26  so.let.the.games.begin (162.252.205.139)  175.386 ms  174.180 ms  175.965 ms
    +27  a.heinous.crime (162.252.205.140)  180.857 ms  180.766 ms  180.192 ms
    +28  a.show.of.force (162.252.205.141)  187.942 ms  186.669 ms  186.986 ms
    +29  a.murder.would.be.nice.of.course (162.252.205.142)  191.349 ms  191.939 ms  190.740 ms
    +30  bad.horse (162.252.205.143)  195.425 ms  195.716 ms  196.186 ms
    +31  bad.horse (162.252.205.144)  199.238 ms  200.620 ms  200.318 ms
    +32  bad.horse (162.252.205.145)  207.554 ms  206.729 ms  205.201 ms
    +33  he-s.bad (162.252.205.146)  211.087 ms  211.649 ms  211.712 ms
    +34  the.evil.league.of.evil (162.252.205.147)  212.657 ms  216.777 ms  216.589 ms
    +35  is.watching.so.beware (162.252.205.148)  220.911 ms  220.326 ms  221.961 ms
    +36  the.grade.that.you.receive (162.252.205.149)  225.384 ms  225.696 ms  225.640 ms
    +37  will.be.your.last.we.swear (162.252.205.150)  232.312 ms  230.989 ms  230.919 ms
    +38  so.make.the.bad.horse.gleeful (162.252.205.151)  235.761 ms  235.291 ms  235.585 ms
    +39  or.he-ll.make.you.his.mare (162.252.205.152)  241.350 ms  239.407 ms  238.394 ms
    +40  o_o (162.252.205.153)  246.154 ms  247.650 ms  247.110 ms
    +41  you-re.saddled.up (162.252.205.154)  250.925 ms  250.401 ms  250.619 ms
    +42  there-s.no.recourse (162.252.205.155)  256.071 ms  251.154 ms  255.340 ms
    +43  it-s.hi-ho.silver (162.252.205.156)  260.152 ms  261.775 ms  261.544 ms
    +44  signed.bad.horse (162.252.205.157)  262.430 ms  261.410 ms  261.365 ms
     

    2. ASCII cinema


    @@ -128,20 +128,20 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #include <stdio.h>
    +
    #include <stdio.h>
     
    -int main(void) {
    -  int array[5] = { 1, 2, 3, 4, 5 };
    +int main(void) {
    +  int array[5] = { 1, 2, 3, 4, 5 };
     
    -  for (int i = 0; i < 5; i++)
    -    printf("%d\n", array[i]);
    +  for (int i = 0; i < 5; i++)
    +    printf("%d\n", array[i]);
     
    -  for (int i = 0; i < 5; i++)
    -    printf("%d\n", i[array]);
    +  for (int i = 0; i < 5; i++)
    +    printf("%d\n", i[array]);
     
    -  for (int i = 0; i < 5; i++)
    -    printf("%d\n", *(i + array));
    -}
    +  for (int i = 0; i < 5; i++)
    +    printf("%d\n", *(i + array));
    +}
     

    5. Variables with prefix $


    @@ -152,20 +152,20 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #include <stdio.h>
    +
    #include <stdio.h>
     
    -int main(void) {
    -  int $array[5] = { 1, 2, 3, 4, 5 };
    +int main(void) {
    +  int $array[5] = { 1, 2, 3, 4, 5 };
     
    -  for (int $i = 0; $i < 5; $i++)
    -    printf("%d\n", $array[$i]);
    +  for (int $i = 0; $i < 5; $i++)
    +    printf("%d\n", $array[$i]);
     
    -  for (int $i = 0; $i < 5; $i++)
    -    printf("%d\n", $i[$array]);
    +  for (int $i = 0; $i < 5; $i++)
    +    printf("%d\n", $i[$array]);
     
    -  for (int $i = 0; $i < 5; $i++)
    -    printf("%d\n", *($i + $array));
    -}
    +  for (int $i = 0; $i < 5; $i++)
    +    printf("%d\n", *($i + $array));
    +}
     

    6. Object oriented shell scripts using ksh


    @@ -176,40 +176,40 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/ksh93
    - 
    -typeset -T Point_t=(
    -    integer -h 'x coordinate' x=0
    -    integer -h 'y coordinate' y=0
    -    typeset -h 'point color'  color="red"
    +
    #!/usr/bin/ksh93
    + 
    +typeset -T Point_t=(
    +    integer -h 'x coordinate' x=0
    +    integer -h 'y coordinate' y=0
    +    typeset -h 'point color'  color="red"
     
    -    function getcolor {
    -        print -r ${_.color}
    -    }
    +    function getcolor {
    +        print -r ${_.color}
    +    }
     
    -    function setcolor {
    -        _.color=$1
    -    }
    +    function setcolor {
    +        _.color=$1
    +    }
     
    -    setxy() {
    -        _.x=$1; _.y=$2
    -    }
    +    setxy() {
    +        _.x=$1; _.y=$2
    +    }
     
    -    getxy() {
    -        print -r "(${_.x},${_.y})"
    -    }
    -)
    - 
    -Point_t point
    - 
    -echo "Initial coordinates are (${point.x},${point.y}). Color is ${point.color}"
    - 
    -point.setxy 5 6
    -point.setcolor blue
    - 
    -echo "New coordinates are ${point.getxy}. Color is ${point.getcolor}"
    - 
    -exit 0
    +    getxy() {
    +        print -r "(${_.x},${_.y})"
    +    }
    +)
    + 
    +Point_t point
    + 
    +echo "Initial coordinates are (${point.x},${point.y}). Color is ${point.color}"
    + 
    +point.setxy 5 6
    +point.setcolor blue
    + 
    +echo "New coordinates are ${point.getxy}. Color is ${point.getcolor}"
    + 
    +exit 0
     

    Using types to create object oriented Korn shell 93 scripts
    @@ -222,18 +222,18 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    package main
    +
    package main
     
    -import "fmt"
    +import "fmt"
     
    -func main() {
    -	var i int
    -	f := func() *int {
    -		return &i
    -	}
    -	*f()++
    -	fmt.Println(i)
    -}
    +func main() {
    +	var i int
    +	f := func() *int {
    +		return &i
    +	}
    +	*f()++
    +	fmt.Println(i)
    +}
     

    Go playground
    diff --git a/gemfeed/2024-10-02-gemtexter-3.0.0-lets-gemtext-again-4.html b/gemfeed/2024-10-02-gemtexter-3.0.0-lets-gemtext-again-4.html index 90d1559b..e5b49ae4 100644 --- a/gemfeed/2024-10-02-gemtexter-3.0.0-lets-gemtext-again-4.html +++ b/gemfeed/2024-10-02-gemtexter-3.0.0-lets-gemtext-again-4.html @@ -76,7 +76,7 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    declare -xr HTML_THEME_DIR=./extras/html/themes/simple
    +
    declare -xr HTML_THEME_DIR=./extras/html/themes/simple
     

    To customize the theme or create your own, simply copy the theme directory and modify it as needed. This makes it also much easier to switch between layouts.
    diff --git a/gemfeed/2024-12-03-f3s-kubernetes-with-freebsd-part-2.html b/gemfeed/2024-12-03-f3s-kubernetes-with-freebsd-part-2.html index ed495210..9c2b2d0b 100644 --- a/gemfeed/2024-12-03-f3s-kubernetes-with-freebsd-part-2.html +++ b/gemfeed/2024-12-03-f3s-kubernetes-with-freebsd-part-2.html @@ -123,9 +123,9 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [paul@earth]~/Downloads% sudo dd \
    -  if=FreeBSD-14.1-RELEASE-amd64-bootonly.iso \
    -  of=/dev/sda conv=sync
    +
    [paul@earth]~/Downloads% sudo dd \
    +  if=FreeBSD-14.1-RELEASE-amd64-bootonly.iso \
    +  of=/dev/sda conv=sync
     

    Next, I plugged the Beelinks (one after another) into my monitor via HDMI (the resolution of the FreeBSD text console seems strangely stretched, as I am using the LG Dual Up monitor), connected Ethernet, an external USB keyboard, and the FreeBSD USB stick, and booted the devices up. With F7, I entered the boot menu and selected the USB stick for the FreeBSD installation.
    @@ -151,9 +151,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # freebsd-update fetch
    -root@f0:~ # freebsd-update install
    -root@f0:~ # freebsd-update reboot
    +
    root@f0:~ # freebsd-update fetch
    +root@f0:~ # freebsd-update install
    +root@f0:~ # freebsd-update reboot
     

    I also added the following entries for the three FreeBSD boxes to the /etc/hosts file:
    @@ -162,11 +162,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # cat <<END >>/etc/hosts
    -192.168.1.130 f0 f0.lan f0.lan.buetow.org
    -192.168.1.131 f1 f1.lan f1.lan.buetow.org
    -192.168.1.132 f2 f2.lan f2.lan.buetow.org
    -END
    +
    root@f0:~ # cat <<END >>/etc/hosts
    +192.168.1.130 f0 f0.lan f0.lan.buetow.org
    +192.168.1.131 f1 f1.lan f1.lan.buetow.org
    +192.168.1.132 f2 f2.lan f2.lan.buetow.org
    +END
     

    You might wonder why bother using the hosts file? Why not use DNS properly? The reason is simplicity. I don't manage 100 hosts, only a few here and there. Having an OpenWRT router in my home, I could also configure everything there, but maybe I'll do that later. For now, keep it simple and straightforward.
    @@ -179,7 +179,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # pkg install helix doas zfs-periodic uptimed
    +
    root@f0:~ # pkg install helix doas zfs-periodic uptimed
     

    Helix editor


    @@ -196,7 +196,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # cp /usr/local/etc/doas.conf.sample /usr/local/etc/doas.conf
    +
    root@f0:~ # cp /usr/local/etc/doas.conf.sample /usr/local/etc/doas.conf
     

    https://man.openbsd.org/doas
    @@ -209,17 +209,17 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # cat <<END >>/etc/periodic.conf
    -daily_zfs_snapshot_enable="YES"
    -daily_zfs_snapshot_pools="zroot"
    -daily_zfs_snapshot_keep="7"
    -weekly_zfs_snapshot_enable="YES"
    -weekly_zfs_snapshot_pools="zroot"
    -weekly_zfs_snapshot_keep="5"
    -monthly_zfs_snapshot_enable="YES"
    -monthly_zfs_snapshot_pools="zroot"
    -monthly_zfs_snapshot_keep="6"
    -END
    +
    root@f0:~ # cat <<END >>/etc/periodic.conf
    +daily_zfs_snapshot_enable="YES"
    +daily_zfs_snapshot_pools="zroot"
    +daily_zfs_snapshot_keep="7"
    +weekly_zfs_snapshot_enable="YES"
    +weekly_zfs_snapshot_pools="zroot"
    +weekly_zfs_snapshot_keep="5"
    +monthly_zfs_snapshot_enable="YES"
    +monthly_zfs_snapshot_pools="zroot"
    +monthly_zfs_snapshot_keep="6"
    +END
     

    https://github.com/ross/zfs-periodic
    @@ -232,9 +232,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # cp /usr/local/mimecast/etc/uptimed.conf-dist \
    -  /usr/local/mimecast/etc/uptimed.conf 
    -root@f0:~ # hx /usr/local/mimecast/etc/uptimed.conf
    +
    root@f0:~ # cp /usr/local/mimecast/etc/uptimed.conf-dist \
    +  /usr/local/mimecast/etc/uptimed.conf 
    +root@f0:~ # hx /usr/local/mimecast/etc/uptimed.conf
     

    In the Helix editor session, I changed LOG_MAXIMUM_ENTRIES to 0 to keep all uptime entries forever and not cut off at 50 (the default config). After that, I enabled and started uptimed:
    @@ -243,8 +243,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # service uptimed enable
    -root@f0:~ # service uptimed start
    +
    root@f0:~ # service uptimed enable
    +root@f0:~ # service uptimed start
     

    To check the current uptime stats, I can now run uprecords:
    @@ -253,15 +253,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
     root@f0:~ # uprecords
    -     #               Uptime | System                                     Boot up
    -----------------------------+---------------------------------------------------
    -->   1     0 days, 00:07:34 | FreeBSD 14.1-RELEASE      Mon Dec  2 12:21:44 2024
    -----------------------------+---------------------------------------------------
    -NewRec     0 days, 00:07:33 | since                     Mon Dec  2 12:21:44 2024
    -    up     0 days, 00:07:34 | since                     Mon Dec  2 12:21:44 2024
    -  down     0 days, 00:00:00 | since                     Mon Dec  2 12:21:44 2024
    -   %up              100.000 | since                     Mon Dec  2 12:21:44 2024
    +
     root@f0:~ # uprecords
    +     #               Uptime | System                                     Boot up
    +----------------------------+---------------------------------------------------
    +->   1     0 days, 00:07:34 | FreeBSD 14.1-RELEASE      Mon Dec  2 12:21:44 2024
    +----------------------------+---------------------------------------------------
    +NewRec     0 days, 00:07:33 | since                     Mon Dec  2 12:21:44 2024
    +    up     0 days, 00:07:34 | since                     Mon Dec  2 12:21:44 2024
    +  down     0 days, 00:00:00 | since                     Mon Dec  2 12:21:44 2024
    +   %up              100.000 | since                     Mon Dec  2 12:21:44 2024
     

    This is how I track the uptimes for all of my host:
    @@ -279,17 +279,17 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % ifconfig re0
    -re0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
    -        options=8209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE>
    -        ether e8:ff:1e:d7:1c:ac
    -        inet 192.168.1.130 netmask 0xffffff00 broadcast 192.168.1.255
    -        inet6 fe80::eaff:1eff:fed7:1cac%re0 prefixlen 64 scopeid 0x1
    -        inet6 fd22:c702:acb7:0:eaff:1eff:fed7:1cac prefixlen 64 detached autoconf
    -        inet6 2a01:5a8:304:1d5c:eaff:1eff:fed7:1cac prefixlen 64 autoconf pltime 10800 vltime 14400
    -        media: Ethernet autoselect (1000baseT <full-duplex>)
    -        status: active
    -        nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
    +
    paul@f0:~ % ifconfig re0
    +re0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
    +        options=8209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE>
    +        ether e8:ff:1e:d7:1c:ac
    +        inet 192.168.1.130 netmask 0xffffff00 broadcast 192.168.1.255
    +        inet6 fe80::eaff:1eff:fed7:1cac%re0 prefixlen 64 scopeid 0x1
    +        inet6 fd22:c702:acb7:0:eaff:1eff:fed7:1cac prefixlen 64 detached autoconf
    +        inet6 2a01:5a8:304:1d5c:eaff:1eff:fed7:1cac prefixlen 64 autoconf pltime 10800 vltime 14400
    +        media: Ethernet autoselect (1000baseT <full-duplex>)
    +        status: active
    +        nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
     

    RAM


    @@ -300,8 +300,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % sysctl hw.physmem
    -hw.physmem: 16902905856
    +
    paul@f0:~ % sysctl hw.physmem
    +hw.physmem: 16902905856
     
     

    @@ -313,11 +313,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % sysctl dev.cpu | grep freq:
    -dev.cpu.3.freq: 705
    -dev.cpu.2.freq: 705
    -dev.cpu.1.freq: 604
    -dev.cpu.0.freq: 604
    +
    paul@f0:~ % sysctl dev.cpu | grep freq:
    +dev.cpu.3.freq: 705
    +dev.cpu.2.freq: 705
    +dev.cpu.1.freq: 604
    +dev.cpu.0.freq: 604
     

    CPU throttling


    @@ -328,14 +328,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas pkg install ubench
    -paul@f0:~ % rehash # For tcsh to find the newly installed command
    -paul@f0:~ % ubench &
    -paul@f0:~ % sysctl dev.cpu | grep freq:
    -dev.cpu.3.freq: 2922
    -dev.cpu.2.freq: 2922
    -dev.cpu.1.freq: 2923
    -dev.cpu.0.freq: 2922
    +
    paul@f0:~ % doas pkg install ubench
    +paul@f0:~ % rehash # For tcsh to find the newly installed command
    +paul@f0:~ % ubench &
    +paul@f0:~ % sysctl dev.cpu | grep freq:
    +dev.cpu.3.freq: 2922
    +dev.cpu.2.freq: 2922
    +dev.cpu.1.freq: 2923
    +dev.cpu.0.freq: 2922
     

    Idle, all three Beelinks plus the switch consumed 26.2W. But with ubench stressing all the CPUs, it went up to 38.8W.
    diff --git a/gemfeed/2024-12-15-random-helix-themes.html b/gemfeed/2024-12-15-random-helix-themes.html index f6adf0d5..b58956ba 100644 --- a/gemfeed/2024-12-15-random-helix-themes.html +++ b/gemfeed/2024-12-15-random-helix-themes.html @@ -25,33 +25,33 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    export EDITOR=hx
    -export VISUAL=$EDITOR
    -export GIT_EDITOR=$EDITOR
    -export HELIX_CONFIG_DIR=$HOME/.config/helix
    +
    export EDITOR=hx
    +export VISUAL=$EDITOR
    +export GIT_EDITOR=$EDITOR
    +export HELIX_CONFIG_DIR=$HOME/.config/helix
     
    -editor::helix::random_theme () {
    -    # May add more theme search paths based on OS. This one is
    -    # for Fedora Linux, but there is also MacOS, etc.
    -    local -r theme_dir=/usr/share/helix/runtime/themes
    -    if [ ! -d $theme_dir ]; then
    -        echo "Helix theme dir $theme_dir doesnt exist"
    -        return 1
    -    fi
    +editor::helix::random_theme () {
    +    # May add more theme search paths based on OS. This one is
    +    # for Fedora Linux, but there is also MacOS, etc.
    +    local -r theme_dir=/usr/share/helix/runtime/themes
    +    if [ ! -d $theme_dir ]; then
    +        echo "Helix theme dir $theme_dir doesnt exist"
    +        return 1
    +    fi
     
    -    local -r config_file=$HELIX_CONFIG_DIR/config.toml
    -    local -r random_theme="$(basename "$(ls $theme_dir \
    -        | grep -v random.toml | grep .toml | sort -R \
    -        | head -n 1)" | cut -d. -f1)"
    +    local -r config_file=$HELIX_CONFIG_DIR/config.toml
    +    local -r random_theme="$(basename "$(ls $theme_dir \
    +        | grep -v random.toml | grep .toml | sort -R \
    +        | head -n 1)" | cut -d. -f1)"
     
    -    sed "/^theme =/ { s/.*/theme = \"$random_theme\"/; }" \
    -        $config_file > $config_file.tmp && 
    -        mv $config_file.tmp $config_file
    -}
    +    sed "/^theme =/ { s/.*/theme = \"$random_theme\"/; }" \
    +        $config_file > $config_file.tmp && 
    +        mv $config_file.tmp $config_file
    +}
     
    -if [ -f $HELIX_CONFIG_DIR/config.toml ]; then
    -    editor::helix::random_theme
    -fi
    +if [ -f $HELIX_CONFIG_DIR/config.toml ]; then
    +    editor::helix::random_theme
    +fi
     

    So every time I open a new terminal or shell, editor::helix::random_theme gets called, which randomly selects a theme from all installed ones and updates the helix config accordingly.
    @@ -60,16 +60,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [paul@earth] ~ % editor::helix::random_theme
    -[paul@earth] ~ % head -n 1 ~/.config/helix/config.toml
    -theme = "jellybeans"
    -[paul@earth] ~ % editor::helix::random_theme
    -[paul@earth] ~ % head -n 1 ~/.config/helix/config.toml
    -theme = "rose_pine"
    -[paul@earth] ~ % editor::helix::random_theme
    -[paul@earth] ~ % head -n 1 ~/.config/helix/config.toml
    -theme = "noctis"
    -[paul@earth] ~ %
    +
    [paul@earth] ~ % editor::helix::random_theme
    +[paul@earth] ~ % head -n 1 ~/.config/helix/config.toml
    +theme = "jellybeans"
    +[paul@earth] ~ % editor::helix::random_theme
    +[paul@earth] ~ % head -n 1 ~/.config/helix/config.toml
    +theme = "rose_pine"
    +[paul@earth] ~ % editor::helix::random_theme
    +[paul@earth] ~ % head -n 1 ~/.config/helix/config.toml
    +theme = "noctis"
    +[paul@earth] ~ %
     

    A better version


    @@ -80,33 +80,33 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    export EDITOR=hx
    -export VISUAL=$EDITOR
    -export GIT_EDITOR=$EDITOR
    -export HELIX_CONFIG_DIR=$HOME/.config/helix
    +
    export EDITOR=hx
    +export VISUAL=$EDITOR
    +export GIT_EDITOR=$EDITOR
    +export HELIX_CONFIG_DIR=$HOME/.config/helix
     
    -editor::helix::theme::get_random () {
    -    for dir in $(hx --health \
    -        | awk '/^Runtime directories/ { print $3 }' | tr ';' ' '); do
    -        if [ -d $dir/themes ]; then
    -            ls $dir/themes
    -        fi
    -    done | grep -F .toml | sort -R | head -n 1 | cut -d. -f1
    -}
    +editor::helix::theme::get_random () {
    +    for dir in $(hx --health \
    +        | awk '/^Runtime directories/ { print $3 }' | tr ';' ' '); do
    +        if [ -d $dir/themes ]; then
    +            ls $dir/themes
    +        fi
    +    done | grep -F .toml | sort -R | head -n 1 | cut -d. -f1
    +}
     
    -editor::helix::theme::set () {
    -    local -r theme="$1"; shift
    +editor::helix::theme::set () {
    +    local -r theme="$1"; shift
     
    -    local -r config_file=$HELIX_CONFIG_DIR/config.toml
    +    local -r config_file=$HELIX_CONFIG_DIR/config.toml
     
    -    sed "/^theme =/ { s/.*/theme = \"$theme\"/; }" \
    -        $config_file > $config_file.tmp && 
    -        mv $config_file.tmp $config_file
    -}
    +    sed "/^theme =/ { s/.*/theme = \"$theme\"/; }" \
    +        $config_file > $config_file.tmp && 
    +        mv $config_file.tmp $config_file
    +}
     
    -if [ -f $HELIX_CONFIG_DIR/config.toml ]; then
    -    editor::helix::theme::set $(editor::helix::theme::get_random)
    -fi
    +if [ -f $HELIX_CONFIG_DIR/config.toml ]; then
    +    editor::helix::theme::set $(editor::helix::theme::get_random)
    +fi
     

    I hope you had some fun. E-Mail your comments to paul@nospam.buetow.org :-)
    diff --git a/gemfeed/2025-02-01-f3s-kubernetes-with-freebsd-part-3.html b/gemfeed/2025-02-01-f3s-kubernetes-with-freebsd-part-3.html index a9d6bd4d..335a9cb7 100644 --- a/gemfeed/2025-02-01-f3s-kubernetes-with-freebsd-part-3.html +++ b/gemfeed/2025-02-01-f3s-kubernetes-with-freebsd-part-3.html @@ -59,11 +59,11 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0: ~ % doas freebsd-update fetch
    -paul@f0: ~ % doas freebsd-update install
    -paul@f0: ~ % doas freebsd-update -r 14.2-RELEASE upgrade
    -paul@f0: ~ % doas freebsd-update install
    -paul@f0: ~ % doas shutdown -r now
    +
    paul@f0: ~ % doas freebsd-update fetch
    +paul@f0: ~ % doas freebsd-update install
    +paul@f0: ~ % doas freebsd-update -r 14.2-RELEASE upgrade
    +paul@f0: ~ % doas freebsd-update install
    +paul@f0: ~ % doas shutdown -r now
     

    And after rebooting, I ran:
    @@ -72,10 +72,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0: ~ % doas freebsd-update install
    -paul@f0: ~ % doas pkg update
    -paul@f0: ~ % doas pkg upgrade
    -paul@f0: ~ % doas shutdown -r now
    +
    paul@f0: ~ % doas freebsd-update install
    +paul@f0: ~ % doas pkg update
    +paul@f0: ~ % doas pkg upgrade
    +paul@f0: ~ % doas shutdown -r now
     

    And after another reboot, I was on 14.2:
    @@ -84,9 +84,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % uname -a
    -FreeBSD f0.lan.buetow.org 14.2-RELEASE FreeBSD 14.2-RELEASE 
    - releng/14.2-n269506-c8918d6c7412 GENERIC amd64
    +
    paul@f0:~ % uname -a
    +FreeBSD f0.lan.buetow.org 14.2-RELEASE FreeBSD 14.2-RELEASE 
    + releng/14.2-n269506-c8918d6c7412 GENERIC amd64
     

    And, of course, I ran this on all 3 nodes!
    @@ -132,8 +132,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0: ~ % doas dmesg | grep UPS
    -ugen0.2: <American Power Conversion Back-UPS BX750MI> at usbus0
    +
    paul@f0: ~ % doas dmesg | grep UPS
    +ugen0.2: <American Power Conversion Back-UPS BX750MI> at usbus0
     

    apcupsd Installation


    @@ -144,7 +144,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0: ~ % doas install apcupsd
    +
    paul@f0: ~ % doas install apcupsd
     

    I have made the following modifications to the configuration file so that the UPS can be used via the USB interface:
    @@ -153,29 +153,29 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/usr/local/etc/apcupsd % diff -u apcupsd.conf.sample  apcupsd.conf
    ---- apcupsd.conf.sample 2024-11-01 16:40:42.000000000 +0200
    -+++ apcupsd.conf        2024-12-03 10:58:24.009501000 +0200
    -@@ -31,7 +31,7 @@
    - #     940-1524C, 940-0024G, 940-0095A, 940-0095B,
    - #     940-0095C, 940-0625A, M-04-02-2000
    - #
    --UPSCABLE smart
    -+UPSCABLE usb
    +
    paul@f0:/usr/local/etc/apcupsd % diff -u apcupsd.conf.sample  apcupsd.conf
    +--- apcupsd.conf.sample 2024-11-01 16:40:42.000000000 +0200
    ++++ apcupsd.conf        2024-12-03 10:58:24.009501000 +0200
    +@@ -31,7 +31,7 @@
    + #     940-1524C, 940-0024G, 940-0095A, 940-0095B,
    + #     940-0095C, 940-0625A, M-04-02-2000
    + #
    +-UPSCABLE smart
    ++UPSCABLE usb
     
    - # To get apcupsd to work, in addition to defining the cable
    - # above, you must also define a UPSTYPE, which corresponds to
    -@@ -88,8 +88,10 @@
    - #                            that apcupsd binds to that particular unit
    - #                            (helpful if you have more than one USB UPS).
    - #
    --UPSTYPE apcsmart
    --DEVICE /dev/usv
    -+UPSTYPE usb
    -+DEVICE
    + # To get apcupsd to work, in addition to defining the cable
    + # above, you must also define a UPSTYPE, which corresponds to
    +@@ -88,8 +88,10 @@
    + #                            that apcupsd binds to that particular unit
    + #                            (helpful if you have more than one USB UPS).
    + #
    +-UPSTYPE apcsmart
    +-DEVICE /dev/usv
    ++UPSTYPE usb
    ++DEVICE
     
    - # POLLTIME <int>
    - #   Interval (in seconds) at which apcupsd polls the UPS for status. This
    + # POLLTIME <int>
    + #   Interval (in seconds) at which apcupsd polls the UPS for status. This
     

    I left the remaining settings as the default ones; for example, the following are of main interest:
    @@ -198,10 +198,10 @@ MINUTES 3 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/usr/local/etc/apcupsd % doas sysrc apcupsd_enable=YES
    -apcupsd_enable:  -> YES
    -paul@f0:/usr/local/etc/apcupsd % doas service apcupsd start
    -Starting apcupsd.
    +
    paul@f0:/usr/local/etc/apcupsd % doas sysrc apcupsd_enable=YES
    +apcupsd_enable:  -> YES
    +paul@f0:/usr/local/etc/apcupsd % doas service apcupsd start
    +Starting apcupsd.
     

    UPS Connectivity Test


    @@ -212,43 +212,43 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % apcaccess
    -APC      : 001,035,0857
    -DATE     : 2025-01-26 14:43:27 +0200
    -HOSTNAME : f0.lan.buetow.org
    -VERSION  : 3.14.14 (31 May 2016) freebsd
    -UPSNAME  : f0.lan.buetow.org
    -CABLE    : USB Cable
    -DRIVER   : USB UPS Driver
    -UPSMODE  : Stand Alone
    -STARTTIME: 2025-01-26 14:43:25 +0200
    -MODEL    : Back-UPS BX750MI
    -STATUS   : ONLINE
    -LINEV    : 230.0 Volts
    -LOADPCT  : 4.0 Percent
    -BCHARGE  : 100.0 Percent
    -TIMELEFT : 65.3 Minutes
    -MBATTCHG : 5 Percent
    -MINTIMEL : 3 Minutes
    -MAXTIME  : 0 Seconds
    -SENSE    : Medium
    -LOTRANS  : 145.0 Volts
    -HITRANS  : 295.0 Volts
    -ALARMDEL : No alarm
    -BATTV    : 13.6 Volts
    -LASTXFER : Automatic or explicit self test
    -NUMXFERS : 0
    -TONBATT  : 0 Seconds
    -CUMONBATT: 0 Seconds
    -XOFFBATT : N/A
    -SELFTEST : NG
    -STATFLAG : 0x05000008
    -SERIALNO : 9B2414A03599
    -BATTDATE : 2001-01-01
    -NOMINV   : 230 Volts
    -NOMBATTV : 12.0 Volts
    -NOMPOWER : 410 Watts
    -END APC  : 2025-01-26 14:44:06 +0200
    +
    paul@f0:~ % apcaccess
    +APC      : 001,035,0857
    +DATE     : 2025-01-26 14:43:27 +0200
    +HOSTNAME : f0.lan.buetow.org
    +VERSION  : 3.14.14 (31 May 2016) freebsd
    +UPSNAME  : f0.lan.buetow.org
    +CABLE    : USB Cable
    +DRIVER   : USB UPS Driver
    +UPSMODE  : Stand Alone
    +STARTTIME: 2025-01-26 14:43:25 +0200
    +MODEL    : Back-UPS BX750MI
    +STATUS   : ONLINE
    +LINEV    : 230.0 Volts
    +LOADPCT  : 4.0 Percent
    +BCHARGE  : 100.0 Percent
    +TIMELEFT : 65.3 Minutes
    +MBATTCHG : 5 Percent
    +MINTIMEL : 3 Minutes
    +MAXTIME  : 0 Seconds
    +SENSE    : Medium
    +LOTRANS  : 145.0 Volts
    +HITRANS  : 295.0 Volts
    +ALARMDEL : No alarm
    +BATTV    : 13.6 Volts
    +LASTXFER : Automatic or explicit self test
    +NUMXFERS : 0
    +TONBATT  : 0 Seconds
    +CUMONBATT: 0 Seconds
    +XOFFBATT : N/A
    +SELFTEST : NG
    +STATFLAG : 0x05000008
    +SERIALNO : 9B2414A03599
    +BATTDATE : 2001-01-01
    +NOMINV   : 230 Volts
    +NOMBATTV : 12.0 Volts
    +NOMPOWER : 410 Watts
    +END APC  : 2025-01-26 14:44:06 +0200
     

    APC Info on Partner Nodes:


    @@ -267,10 +267,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f1:~ % apcaccess -h f0.lan.buetow.org | grep Percent
    -LOADPCT  : 12.0 Percent
    -BCHARGE  : 94.0 Percent
    -MBATTCHG : 5 Percent
    +
    paul@f1:~ % apcaccess -h f0.lan.buetow.org | grep Percent
    +LOADPCT  : 12.0 Percent
    +BCHARGE  : 94.0 Percent
    +MBATTCHG : 5 Percent
     

    But I want the daemon to be configured and enabled in such a way that it connects to the master UPS node (the one with the UPS connected via USB) so that it can also initiate a system shutdown when the UPS battery reaches low levels. For that, apcupsd itself needs to be aware of the UPS status.
    @@ -281,52 +281,52 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f2:/usr/local/etc/apcupsd % diff -u apcupsd.conf.sample apcupsd.conf
    ---- apcupsd.conf.sample 2024-11-01 16:40:42.000000000 +0200
    -+++ apcupsd.conf        2025-01-26 15:52:45.108469000 +0200
    -@@ -31,7 +31,7 @@
    - #     940-1524C, 940-0024G, 940-0095A, 940-0095B,
    - #     940-0095C, 940-0625A, M-04-02-2000
    - #
    --UPSCABLE smart
    -+UPSCABLE ether
    +
    paul@f2:/usr/local/etc/apcupsd % diff -u apcupsd.conf.sample apcupsd.conf
    +--- apcupsd.conf.sample 2024-11-01 16:40:42.000000000 +0200
    ++++ apcupsd.conf        2025-01-26 15:52:45.108469000 +0200
    +@@ -31,7 +31,7 @@
    + #     940-1524C, 940-0024G, 940-0095A, 940-0095B,
    + #     940-0095C, 940-0625A, M-04-02-2000
    + #
    +-UPSCABLE smart
    ++UPSCABLE ether
     
    - # To get apcupsd to work, in addition to defining the cable
    - # above, you must also define a UPSTYPE, which corresponds to
    -@@ -52,7 +52,6 @@
    - #                            Network Information Server. This is used if the
    - #                            UPS powering your computer is connected to a
    - #                            different computer for monitoring.
    --#
    - # snmp      hostname:port:vendor:community
    - #                            SNMP network link to an SNMP-enabled UPS device.
    - #                            Hostname is the ip address or hostname of the UPS
    -@@ -88,8 +87,8 @@
    - #                            that apcupsd binds to that particular unit
    - #                            (helpful if you have more than one USB UPS).
    - #
    --UPSTYPE apcsmart
    --DEVICE /dev/usv
    -+UPSTYPE net
    -+DEVICE f0.lan.buetow.org:3551
    + # To get apcupsd to work, in addition to defining the cable
    + # above, you must also define a UPSTYPE, which corresponds to
    +@@ -52,7 +52,6 @@
    + #                            Network Information Server. This is used if the
    + #                            UPS powering your computer is connected to a
    + #                            different computer for monitoring.
    +-#
    + # snmp      hostname:port:vendor:community
    + #                            SNMP network link to an SNMP-enabled UPS device.
    + #                            Hostname is the ip address or hostname of the UPS
    +@@ -88,8 +87,8 @@
    + #                            that apcupsd binds to that particular unit
    + #                            (helpful if you have more than one USB UPS).
    + #
    +-UPSTYPE apcsmart
    +-DEVICE /dev/usv
    ++UPSTYPE net
    ++DEVICE f0.lan.buetow.org:3551
     
    - # POLLTIME <int>
    - #   Interval (in seconds) at which apcupsd polls the UPS for status. This
    -@@ -147,12 +146,12 @@
    - # If during a power failure, the remaining battery percentage
    - # (as reported by the UPS) is below or equal to BATTERYLEVEL,
    - # apcupsd will initiate a system shutdown.
    --BATTERYLEVEL 5
    -+BATTERYLEVEL 10
    + # POLLTIME <int>
    + #   Interval (in seconds) at which apcupsd polls the UPS for status. This
    +@@ -147,12 +146,12 @@
    + # If during a power failure, the remaining battery percentage
    + # (as reported by the UPS) is below or equal to BATTERYLEVEL,
    + # apcupsd will initiate a system shutdown.
    +-BATTERYLEVEL 5
    ++BATTERYLEVEL 10
     
    - # If during a power failure, the remaining runtime in minutes
    - # (as calculated internally by the UPS) is below or equal to MINUTES,
    - # apcupsd, will initiate a system shutdown.
    --MINUTES 3
    -+MINUTES 6
    + # If during a power failure, the remaining runtime in minutes
    + # (as calculated internally by the UPS) is below or equal to MINUTES,
    + # apcupsd, will initiate a system shutdown.
    +-MINUTES 3
    ++MINUTES 6
     
    - # If during a power failure, the UPS has run on batteries for TIMEOUT
    - # many seconds or longer, apcupsd will initiate a system shutdown.
    + # If during a power failure, the UPS has run on batteries for TIMEOUT
    + # many seconds or longer, apcupsd will initiate a system shutdown.
     
     
    So I also ran the following commands on f1 and f2:
    @@ -335,10 +335,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f1:/usr/local/etc/apcupsd % doas sysrc apcupsd_enable=YES
    -apcupsd_enable:  -> YES
    -paul@f1:/usr/local/etc/apcupsd % doas service apcupsd start
    -Starting apcupsd.
    +
    paul@f1:/usr/local/etc/apcupsd % doas sysrc apcupsd_enable=YES
    +apcupsd_enable:  -> YES
    +paul@f1:/usr/local/etc/apcupsd % doas service apcupsd start
    +Starting apcupsd.
     

    And then I was able to connect to localhost via the apcaccess command:
    @@ -347,10 +347,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f1:~ % doas apcaccess | grep Percent
    -LOADPCT  : 5.0 Percent
    -BCHARGE  : 95.0 Percent
    -MBATTCHG : 5 Percent
    +
    paul@f1:~ % doas apcaccess | grep Percent
    +LOADPCT  : 5.0 Percent
    +BCHARGE  : 95.0 Percent
    +MBATTCHG : 5 Percent
     

    Power outage simulation


    @@ -372,8 +372,8 @@ Power failure. Running on UPS batteries. by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/usr/local/etc/apcupsd % apcaccess -p TIMELEFT
    -63.9 Minutes
    +
    paul@f0:/usr/local/etc/apcupsd % apcaccess -p TIMELEFT
    +63.9 Minutes
     

    And after around one hour (f1 and f2 a bit earlier, f0 a bit later due to the different BATTERYLEVEL and MINUTES settings outlined earlier), the following broadcast was sent out:
    diff --git a/gemfeed/2025-02-08-random-weird-things-ii.html b/gemfeed/2025-02-08-random-weird-things-ii.html index fb87f963..a4076d4d 100644 --- a/gemfeed/2025-02-08-random-weird-things-ii.html +++ b/gemfeed/2025-02-08-random-weird-things-ii.html @@ -79,25 +79,25 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    package main
    +
    package main
     
    -import "log"
    +import "log"
     
    -type fun func() string
    +type fun func() string
     
    -func (f fun) Bar() string {
    -        return "Bar"
    -}
    +func (f fun) Bar() string {
    +        return "Bar"
    +}
     
    -func main() {
    -        var f fun = func() string {
    -                return "Foo"
    -        }
    -        log.Println("Example 1: ", f())
    -        log.Println("Example 2: ", f.Bar())
    -        log.Println("Example 3: ", fun(f.Bar).Bar())
    -        log.Println("Example 4: ", fun(fun(f.Bar).Bar).Bar())
    -}
    +func main() {
    +        var f fun = func() string {
    +                return "Foo"
    +        }
    +        log.Println("Example 1: ", f())
    +        log.Println("Example 2: ", f.Bar())
    +        log.Println("Example 3: ", fun(f.Bar).Bar())
    +        log.Println("Example 4: ", fun(fun(f.Bar).Bar).Bar())
    +}
     

    It runs just fine:
    @@ -106,11 +106,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ❯ go run main.go
    -2025/02/07 22:56:14 Example 1:  Foo
    -2025/02/07 22:56:14 Example 2:  Bar
    -2025/02/07 22:56:14 Example 3:  Bar
    -2025/02/07 22:56:14 Example 4:  Bar
    +
    ❯ go run main.go
    +2025/02/07 22:56:14 Example 1:  Foo
    +2025/02/07 22:56:14 Example 2:  Bar
    +2025/02/07 22:56:14 Example 3:  Bar
    +2025/02/07 22:56:14 Example 4:  Bar
     

    macOS


    @@ -129,20 +129,20 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ❯ touch Maß
    -❯ ls -l
    --rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Maß
    -❯ touch Mass
    -❯ ls -l
    --rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Maß
    -❯ rm Mass
    -❯ ls -l
    +
    ❯ touch Maß
    +❯ ls -l
    +-rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Maß
    +❯ touch Mass
    +❯ ls -l
    +-rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Maß
    +❯ rm Mass
    +❯ ls -l
     
    -❯ touch Mass
    -❯ ls -ltr
    --rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Mass
    -❯ rm Maß
    -❯ ls -l
    +❯ touch Mass
    +❯ ls -ltr
    +-rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Mass
    +❯ rm Maß
    +❯ ls -l
     
     

    @@ -186,16 +186,16 @@ ADFS::4.$.Documents.Techwriter.Myfile by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    arr = {10, 20, 30, 40, 50}
    -print(arr[1]) -- Accessing the first element
    +
    arr = {10, 20, 30, 40, 50}
    +print(arr[1]) -- Accessing the first element
     

    -
    ❯ lua foo.lua
    -10
    +
    ❯ lua foo.lua
    +10
     

    One-based indexing is more natural for human-readable, mathematical, and theoretical contexts, where counting traditionally starts from one.
    @@ -210,45 +210,45 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    # (C) 2006 by Paul C. Buetow
    +
    # (C) 2006 by Paul C. Buetow
     
    -Christmas:{time;#!!!
    +Christmas:{time;#!!!
     
    -Children: do tell $wishes;
    +Children: do tell $wishes;
     
    -Santa: for $each (@children) { 
    -BEGIN { read $each, $their, wishes and study them; use Memoize#ing
    +Santa: for $each (@children) { 
    +BEGIN { read $each, $their, wishes and study them; use Memoize#ing
     
    -} use constant gift, 'wrapping'; 
    -package Gifts; pack $each, gift and bless $each and goto deliver
    -or do import if not local $available,!!! HO, HO, HO;
    +} use constant gift, 'wrapping'; 
    +package Gifts; pack $each, gift and bless $each and goto deliver
    +or do import if not local $available,!!! HO, HO, HO;
     
    -redo Santa, pipe $gifts, to_childs;
    -redo Santa and do return if last one, is, delivered; 
    +redo Santa, pipe $gifts, to_childs;
    +redo Santa and do return if last one, is, delivered; 
     
    -deliver: gift and require diagnostics if our $gifts ,not break;
    -do{ use NEXT; time; tied $gifts} if broken and dump the, broken, ones;
    -The_children: sleep and wait for (each %gift) and try { to => untie $gifts };
    +deliver: gift and require diagnostics if our $gifts ,not break;
    +do{ use NEXT; time; tied $gifts} if broken and dump the, broken, ones;
    +The_children: sleep and wait for (each %gift) and try { to => untie $gifts };
     
    -redo Santa, pipe $gifts, to_childs;
    -redo Santa and do return if last one, is, delivered; 
    +redo Santa, pipe $gifts, to_childs;
    +redo Santa and do return if last one, is, delivered; 
     
    -The_christmas_tree: formline s/ /childrens/, $gifts;
    -alarm and warn if not exists $Christmas{ tree}, @t, $ENV{HOME};  
    -write <<EMail
    - to the parents to buy a new christmas tree!!!!111
    - and send the
    -EMail
    -;wait and redo deliver until defined local $tree;
    +The_christmas_tree: formline s/ /childrens/, $gifts;
    +alarm and warn if not exists $Christmas{ tree}, @t, $ENV{HOME};  
    +write <<EMail
    + to the parents to buy a new christmas tree!!!!111
    + and send the
    +EMail
    +;wait and redo deliver until defined local $tree;
     
    -redo Santa, pipe $gifts, to_childs;
    -redo Santa and do return if last one, is, delivered ;}
    +redo Santa, pipe $gifts, to_childs;
    +redo Santa and do return if last one, is, delivered ;}
     
    -END {} our $mission and do sleep until next Christmas ;}
    +END {} our $mission and do sleep until next Christmas ;}
     
    -__END__
    +__END__
     
    -This is perl, v5.8.8 built for i386-freebsd-64int
    +This is perl, v5.8.8 built for i386-freebsd-64int
     

    More Perl Poetry of mine
    diff --git a/gemfeed/2025-03-05-sharing-on-social-media-with-gos.html b/gemfeed/2025-03-05-sharing-on-social-media-with-gos.html index 024c56a0..0fbdb727 100644 --- a/gemfeed/2025-03-05-sharing-on-social-media-with-gos.html +++ b/gemfeed/2025-03-05-sharing-on-social-media-with-gos.html @@ -84,8 +84,8 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    git clone https://codeberg.org/snonux/gos.git
    -cd gos
    +
    git clone https://codeberg.org/snonux/gos.git
    +cd gos
     

    Build the binaries:
    @@ -94,10 +94,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    go build -o gos ./cmd/gos
    -go build -o gosc ./cmd/gosc
    -sudo mv gos ~/go/bin
    -sudo mv gosc ~/go/bin
    +
    go build -o gos ./cmd/gos
    +go build -o gosc ./cmd/gosc
    +sudo mv gos ~/go/bin
    +sudo mv gosc ~/go/bin
     

    Or, if you want to use the Taskfile:
    @@ -106,7 +106,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    go-task install
    +
    go-task install
     

    Configuration


    @@ -119,13 +119,13 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    {
    -  "MastodonURL": "https://mastodon.example.com",
    -  "MastodonAccessToken": "your-mastodon-access-token",
    -  "LinkedInClientID": "your-linkedin-client-id",
    -  "LinkedInSecret": "your-linkedin-client-secret",
    -  "LinkedInRedirectURL": "http://localhost:8080/callback",
    -}
    +
    {
    +  "MastodonURL": "https://mastodon.example.com",
    +  "MastodonAccessToken": "your-mastodon-access-token",
    +  "LinkedInClientID": "your-linkedin-client-id",
    +  "LinkedInSecret": "your-linkedin-client-secret",
    +  "LinkedInRedirectURL": "http://localhost:8080/callback",
    +}
     

    Configuration fields


    @@ -181,7 +181,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ./gos --dry
    +
    ./gos --dry
     

    *Normal run*
    @@ -192,7 +192,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ./gos 
    +
    ./gos 
     

    :-)
    @@ -357,7 +357,7 @@ Hello World :-) by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    gos --geminiSummaryFor 202410,202411,202412
    +
    gos --geminiSummaryFor 202410,202411,202412
     

    This outputs the summary for the three specified months, as shown in the example. The summary includes posts from all social media networks but removes duplicates.
    @@ -369,7 +369,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    gos --gemtexterEnable --geminiSummaryFor 202410,202411,202412
    +
    gos --gemtexterEnable --geminiSummaryFor 202410,202411,202412
     

    Gemtexter
    @@ -380,7 +380,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    gos --gemtexterEnable --geminiSummaryFor 202410,202411,202412 --geminiCapsules "foo.zone,paul.buetow.org"
    +
    gos --gemtexterEnable --geminiSummaryFor 202410,202411,202412 --geminiCapsules "foo.zone,paul.buetow.org"
     

    It will then also generate Gemini Gemtext links in the summary page and flag them with (Gemini).
    diff --git a/gemfeed/2025-04-05-f3s-kubernetes-with-freebsd-part-4.html b/gemfeed/2025-04-05-f3s-kubernetes-with-freebsd-part-4.html index 96883f2a..5332ee55 100644 --- a/gemfeed/2025-04-05-f3s-kubernetes-with-freebsd-part-4.html +++ b/gemfeed/2025-04-05-f3s-kubernetes-with-freebsd-part-4.html @@ -73,10 +73,10 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % dmesg | grep 'Features2=.*POPCNT'
    -  Features2=0x7ffafbbf<SSE3,PCLMULQDQ,DTES64,MON,DS_CPL,VMX,EST,TM2,SSSE3,SDBG,
    -	FMA,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,TSCDLT,AESNI,XSAVE,
    -	OSXSAVE,AVX,F16C,RDRAND>
    +
    paul@f0:~ % dmesg | grep 'Features2=.*POPCNT'
    +  Features2=0x7ffafbbf<SSE3,PCLMULQDQ,DTES64,MON,DS_CPL,VMX,EST,TM2,SSSE3,SDBG,
    +	FMA,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,TSCDLT,AESNI,XSAVE,
    +	OSXSAVE,AVX,F16C,RDRAND>
     

    So it's there! All good.
    @@ -93,15 +93,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas pkg install vm-bhyve bhyve-firmware
    -paul@f0:~ % doas sysrc vm_enable=YES
    -vm_enable:  -> YES
    -paul@f0:~ % doas sysrc vm_dir=zfs:zroot/bhyve
    -vm_dir:  -> zfs:zroot/bhyve
    -paul@f0:~ % doas zfs create zroot/bhyve
    -paul@f0:~ % doas vm init
    -paul@f0:~ % doas vm switch create public
    -paul@f0:~ % doas vm switch add public re0
    +
    paul@f0:~ % doas pkg install vm-bhyve bhyve-firmware
    +paul@f0:~ % doas sysrc vm_enable=YES
    +vm_enable:  -> YES
    +paul@f0:~ % doas sysrc vm_dir=zfs:zroot/bhyve
    +vm_dir:  -> zfs:zroot/bhyve
    +paul@f0:~ % doas zfs create zroot/bhyve
    +paul@f0:~ % doas vm init
    +paul@f0:~ % doas vm switch create public
    +paul@f0:~ % doas vm switch add public re0
     

    Bhyve stores all it's data in the /bhyve of the zroot ZFS pool:
    @@ -110,8 +110,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % zfs list | grep bhyve
    -zroot/bhyve                                   1.74M   453G  1.74M  /zroot/bhyve
    +
    paul@f0:~ % zfs list | grep bhyve
    +zroot/bhyve                                   1.74M   453G  1.74M  /zroot/bhyve
     

    For convenience, we also create this symlink:
    @@ -120,7 +120,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas ln -s /zroot/bhyve/ /bhyve
    +
    paul@f0:~ % doas ln -s /zroot/bhyve/ /bhyve
     
     

    @@ -130,8 +130,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas vm list
    -NAME  DATASTORE  LOADER  CPU  MEMORY  VNC  AUTO  STATE
    +
    paul@f0:~ % doas vm list
    +NAME  DATASTORE  LOADER  CPU  MEMORY  VNC  AUTO  STATE
     

    Rocky Linux VMs


    @@ -152,10 +152,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas vm iso \
    - https://download.rockylinux.org/pub/rocky/9/isos/x86_64/Rocky-9.5-x86_64-minimal.iso
    -/zroot/bhyve/.iso/Rocky-9.5-x86_64-minimal.iso        1808 MB 4780 kBps 06m28s
    -paul@f0:/bhyve % doas vm create rocky
    +
    paul@f0:~ % doas vm iso \
    + https://download.rockylinux.org/pub/rocky/9/isos/x86_64/Rocky-9.5-x86_64-minimal.iso
    +/zroot/bhyve/.iso/Rocky-9.5-x86_64-minimal.iso        1808 MB 4780 kBps 06m28s
    +paul@f0:/bhyve % doas vm create rocky
     

    VM configuration


    @@ -166,16 +166,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/bhyve/rocky % cat rocky.conf
    -loader="bhyveload"
    -cpu=1
    -memory=256M
    -network0_type="virtio-net"
    -network0_switch="public"
    -disk0_type="virtio-blk"
    -disk0_name="disk0.img"
    -uuid="1c4655ac-c828-11ef-a920-e8ff1ed71ca0"
    -network0_mac="58:9c:fc:0d:13:3f"
    +
    paul@f0:/bhyve/rocky % cat rocky.conf
    +loader="bhyveload"
    +cpu=1
    +memory=256M
    +network0_type="virtio-net"
    +network0_switch="public"
    +disk0_type="virtio-blk"
    +disk0_name="disk0.img"
    +uuid="1c4655ac-c828-11ef-a920-e8ff1ed71ca0"
    +network0_mac="58:9c:fc:0d:13:3f"
     

    The uuid and the network0_mac differ for each of the three VMs (the ones being installed on f0, f1 and f2).
    @@ -206,17 +206,17 @@ network0_mac="58:9c:fc:0d:13:3f" by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas vm install rocky Rocky-9.5-x86_64-minimal.iso
    -Starting rocky
    -  * found guest in /zroot/bhyve/rocky
    -  * booting...
    +
    paul@f0:~ % doas vm install rocky Rocky-9.5-x86_64-minimal.iso
    +Starting rocky
    +  * found guest in /zroot/bhyve/rocky
    +  * booting...
     
    -paul@f0:/bhyve/rocky % doas vm list
    -NAME   DATASTORE  LOADER  CPU  MEMORY  VNC           AUTO  STATE
    -rocky  default    uefi    4    14G     0.0.0.0:5900  No    Locked (f0.lan.buetow.org)
    +paul@f0:/bhyve/rocky % doas vm list
    +NAME   DATASTORE  LOADER  CPU  MEMORY  VNC           AUTO  STATE
    +rocky  default    uefi    4    14G     0.0.0.0:5900  No    Locked (f0.lan.buetow.org)
     
    -paul@f0:/bhyve/rocky % doas sockstat -4 | grep 5900
    -root     bhyve       6079 8   tcp4   *:5900                *:*
    +paul@f0:/bhyve/rocky % doas sockstat -4 | grep 5900
    +root     bhyve       6079 8   tcp4   *:5900                *:*
     

    Port 5900 now also opens for VNC connections, so I connected it with a VNC client and ran through the installation dialogues. This could be done unattended or more automated, but there are only three VMs to install, and the automation doesn't seem worth it as we do it only once a year or less often.
    @@ -229,9 +229,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/bhyve/rocky % doas vm stop rocky
    -paul@f0:/bhyve/rocky % doas truncate -s 100G disk0.img
    -paul@f0:/bhyve/rocky % doas vm install rocky Rocky-9.5-x86_64-minimal.iso
    +
    paul@f0:/bhyve/rocky % doas vm stop rocky
    +paul@f0:/bhyve/rocky % doas truncate -s 100G disk0.img
    +paul@f0:/bhyve/rocky % doas vm install rocky Rocky-9.5-x86_64-minimal.iso
     

    Connect to VNC


    @@ -260,9 +260,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/bhyve/rocky % cat <<END | doas tee -a /etc/rc.conf
    -vm_list="rocky"
    -vm_delay="5"
    +
    paul@f0:/bhyve/rocky % cat <<END | doas tee -a /etc/rc.conf
    +vm_list="rocky"
    +vm_delay="5"
     

    The vm_delay isn't really required. It is used to wait 5 seconds before starting each VM, but there is currently only one VM per host. Maybe later, when there are more, this will be useful. After adding, there's now a Yes indicator in the AUTO column.
    @@ -271,9 +271,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas vm list
    -NAME   DATASTORE  LOADER  CPU  MEMORY  VNC           AUTO     STATE
    -rocky  default    uefi    4    14G     0.0.0.0:5900  Yes [1]  Running (2063)
    +
    paul@f0:~ % doas vm list
    +NAME   DATASTORE  LOADER  CPU  MEMORY  VNC           AUTO     STATE
    +rocky  default    uefi    4    14G     0.0.0.0:5900  Yes [1]  Running (2063)
     

    Static IP configuration


    @@ -292,11 +292,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/bhyve/rocky % cat <<END | doas tee -a /etc/hosts
    -192.168.1.120 r0 r0.lan r0.lan.buetow.org
    -192.168.1.121 r1 r1.lan r1.lan.buetow.org
    -192.168.1.122 r2 r2.lan r2.lan.buetow.org
    -END
    +
    paul@f0:/bhyve/rocky % cat <<END | doas tee -a /etc/hosts
    +192.168.1.120 r0 r0.lan r0.lan.buetow.org
    +192.168.1.121 r1 r1.lan r1.lan.buetow.org
    +192.168.1.122 r2 r2.lan r2.lan.buetow.org
    +END
     

    And we configure the IPs accordingly on the VMs themselves by opening a root shell via SSH to the VMs and entering the following commands on each of the VMs:
    @@ -305,18 +305,18 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] % dnmcli connection modify enp0s5 ipv4.address 192.168.1.120/24
    -[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.gateway 192.168.1.1
    -[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.DNS 192.168.1.1
    -[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.method manual
    -[root@r0 ~] % dnmcli connection down enp0s5
    -[root@r0 ~] % dnmcli connection up enp0s5
    -[root@r0 ~] % hostnamectl set-hostname r0.lan.buetow.org
    -[root@r0 ~] % cat <<END >>/etc/hosts
    -192.168.1.120 r0 r0.lan r0.lan.buetow.org
    -192.168.1.121 r1 r1.lan r1.lan.buetow.org
    -192.168.1.122 r2 r2.lan r2.lan.buetow.org
    -END
    +
    [root@r0 ~] % dnmcli connection modify enp0s5 ipv4.address 192.168.1.120/24
    +[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.gateway 192.168.1.1
    +[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.DNS 192.168.1.1
    +[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.method manual
    +[root@r0 ~] % dnmcli connection down enp0s5
    +[root@r0 ~] % dnmcli connection up enp0s5
    +[root@r0 ~] % hostnamectl set-hostname r0.lan.buetow.org
    +[root@r0 ~] % cat <<END >>/etc/hosts
    +192.168.1.120 r0 r0.lan r0.lan.buetow.org
    +192.168.1.121 r1 r1.lan r1.lan.buetow.org
    +192.168.1.122 r2 r2.lan r2.lan.buetow.org
    +END
     

    Whereas:
    @@ -337,7 +337,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % for i in 0 1 2; do ssh-copy-id root@r$i.lan.buetow.org; done
    +
    % for i in 0 1 2; do ssh-copy-id root@r$i.lan.buetow.org; done
     

    Then, we edit the /etc/ssh/sshd_config file again on all three VMs and configure PasswordAuthentication no to only allow SSH key authentication from now on.
    @@ -348,8 +348,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] % dnf update
    -[root@r0 ~] % reboot
    +
    [root@r0 ~] % dnf update
    +[root@r0 ~] % reboot
     

    Stress testing CPU


    @@ -360,28 +360,28 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    package main
    +
    package main
     
    -import "testing"
    +import "testing"
     
    -func BenchmarkCPUSilly1(b *testing.B) {
    -	for i := 0; i < b.N; i++ {
    -		_ = i * i
    -	}
    -}
    +func BenchmarkCPUSilly1(b *testing.B) {
    +	for i := 0; i < b.N; i++ {
    +		_ = i * i
    +	}
    +}
     
    -func BenchmarkCPUSilly2(b *testing.B) {
    -	var sillyResult float64
    -	for i := 0; i < b.N; i++ {
    -		sillyResult += float64(i)
    -		sillyResult *= float64(i)
    -		divisor := float64(i) + 1
    -		if divisor > 0 {
    -			sillyResult /= divisor
    -		}
    -	}
    -	_ = sillyResult // to avoid compiler optimization
    -}
    +func BenchmarkCPUSilly2(b *testing.B) {
    +	var sillyResult float64
    +	for i := 0; i < b.N; i++ {
    +		sillyResult += float64(i)
    +		sillyResult *= float64(i)
    +		divisor := float64(i) + 1
    +		if divisor > 0 {
    +			sillyResult /= divisor
    +		}
    +	}
    +	_ = sillyResult // to avoid compiler optimization
    +}
     

    You can find the repository here:
    @@ -396,10 +396,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas pkg install git go
    -paul@f0:~ % mkdir ~/git && cd ~/git && \
    -  git clone https://codeberg.org/snonux/sillybench && \
    -  cd sillybench
    +
    paul@f0:~ % doas pkg install git go
    +paul@f0:~ % mkdir ~/git && cd ~/git && \
    +  git clone https://codeberg.org/snonux/sillybench && \
    +  cd sillybench
     

    And to run it:
    @@ -408,18 +408,18 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~/git/sillybench % go version
    -go version go1.24.1 freebsd/amd64
    +
    paul@f0:~/git/sillybench % go version
    +go version go1.24.1 freebsd/amd64
     
    -paul@f0:~/git/sillybench % go test -bench=.
    -goos: freebsd
    -goarch: amd64
    -pkg: codeberg.org/snonux/sillybench
    -cpu: Intel(R) N100
    -BenchmarkCPUSilly1-4    1000000000               0.4022 ns/op
    -BenchmarkCPUSilly2-4    1000000000               0.4027 ns/op
    -PASS
    -ok      codeberg.org/snonux/sillybench 0.891s
    +paul@f0:~/git/sillybench % go test -bench=.
    +goos: freebsd
    +goarch: amd64
    +pkg: codeberg.org/snonux/sillybench
    +cpu: Intel(R) N100
    +BenchmarkCPUSilly1-4    1000000000               0.4022 ns/op
    +BenchmarkCPUSilly2-4    1000000000               0.4027 ns/op
    +PASS
    +ok      codeberg.org/snonux/sillybench 0.891s
     

    Silly Rocky Linux VM @ Bhyve benchmark


    @@ -430,10 +430,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~]# dnf install golang git
    -[root@r0 ~]# mkdir ~/git && cd ~/git && \
    -  git clone https://codeberg.org/snonux/sillybench && \
    -  cd sillybench
    +
    [root@r0 ~]# dnf install golang git
    +[root@r0 ~]# mkdir ~/git && cd ~/git && \
    +  git clone https://codeberg.org/snonux/sillybench && \
    +  cd sillybench
     

    And to run it:
    @@ -442,15 +442,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 sillybench]# go version
    -go version go1.22.9 (Red Hat 1.22.9-2.el9_5) linux/amd64
    -[root@r0 sillybench]# go test -bench=.
    -goos: linux
    -goarch: amd64
    -pkg: codeberg.org/snonux/sillybench
    -cpu: Intel(R) N100
    -BenchmarkCPUSilly1-4    1000000000               0.4347 ns/op
    -BenchmarkCPUSilly2-4    1000000000               0.4345 ns/op
    +
    [root@r0 sillybench]# go version
    +go version go1.22.9 (Red Hat 1.22.9-2.el9_5) linux/amd64
    +[root@r0 sillybench]# go test -bench=.
    +goos: linux
    +goarch: amd64
    +pkg: codeberg.org/snonux/sillybench
    +cpu: Intel(R) N100
    +BenchmarkCPUSilly1-4    1000000000               0.4347 ns/op
    +BenchmarkCPUSilly2-4    1000000000               0.4345 ns/op
     

    The Linux benchmark is slightly slower than the FreeBSD one. The Go version is also a bit older. I tried the same with the up-to-date version of Go (1.24.x) with similar results. There could be a slight Bhyve overhead, or FreeBSD is just slightly more efficient in this benchmark. Overall, this shows that Bhyve performs excellently.
    @@ -465,15 +465,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@freebsd:~/git/sillybench # go test -bench=.
    -goos: freebsd
    -goarch: amd64
    -pkg: codeberg.org/snonux/sillybench
    -cpu: Intel(R) N100
    -BenchmarkCPUSilly1      1000000000               0.4273 ns/op
    -BenchmarkCPUSilly2      1000000000               0.4286 ns/op
    -PASS
    -ok      codeberg.org/snonux/sillybench  0.949s
    +
    root@freebsd:~/git/sillybench # go test -bench=.
    +goos: freebsd
    +goarch: amd64
    +pkg: codeberg.org/snonux/sillybench
    +cpu: Intel(R) N100
    +BenchmarkCPUSilly1      1000000000               0.4273 ns/op
    +BenchmarkCPUSilly2      1000000000               0.4286 ns/op
    +PASS
    +ok      codeberg.org/snonux/sillybench  0.949s
     

    It's a bit better than Linux! I am sure that this is not really a scientific benchmark, so take the results with a grain of salt!
    @@ -490,16 +490,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas ubench -s 1
    -Unix Benchmark Utility v.0.3
    -Copyright (C) July, 1999 PhysTech, Inc.
    -Author: Sergei Viznyuk <sv@phystech.com>
    -http://www.phystech.com/download/ubench.html
    -FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    -Ubench Single CPU:   671010 (0.40s)
    -Ubench Single MEM:  1705237 (0.48s)
    ------------------------------------
    -Ubench Single AVG:  1188123
    +
    paul@f0:~ % doas ubench -s 1
    +Unix Benchmark Utility v.0.3
    +Copyright (C) July, 1999 PhysTech, Inc.
    +Author: Sergei Viznyuk <sv@phystech.com>
    +http://www.phystech.com/download/ubench.html
    +FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    +Ubench Single CPU:   671010 (0.40s)
    +Ubench Single MEM:  1705237 (0.48s)
    +-----------------------------------
    +Ubench Single AVG:  1188123
     
     

    @@ -509,16 +509,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas ubench
    -Unix Benchmark Utility v.0.3
    -Copyright (C) July, 1999 PhysTech, Inc.
    -Author: Sergei Viznyuk <sv@phystech.com>
    -http://www.phystech.com/download/ubench.html
    -FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    -Ubench CPU:  2660220
    -Ubench MEM:  3095182
    ---------------------
    -Ubench AVG:  2877701
    +
    paul@f0:~ % doas ubench
    +Unix Benchmark Utility v.0.3
    +Copyright (C) July, 1999 PhysTech, Inc.
    +Author: Sergei Viznyuk <sv@phystech.com>
    +http://www.phystech.com/download/ubench.html
    +FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    +Ubench CPU:  2660220
    +Ubench MEM:  3095182
    +--------------------
    +Ubench AVG:  2877701
     

    FreeBSD VM @ Bhyve ubench benchmark


    @@ -529,16 +529,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@freebsd:~ # ubench -s 1
    -Unix Benchmark Utility v.0.3
    -Copyright (C) July, 1999 PhysTech, Inc.
    -Author: Sergei Viznyuk <sv@phystech.com>
    -http://www.phystech.com/download/ubench.html
    -FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    -Ubench Single CPU:   672792 (0.40s)
    -Ubench Single MEM:   852757 (0.48s)
    ------------------------------------
    -Ubench Single AVG:   762774
    +
    root@freebsd:~ # ubench -s 1
    +Unix Benchmark Utility v.0.3
    +Copyright (C) July, 1999 PhysTech, Inc.
    +Author: Sergei Viznyuk <sv@phystech.com>
    +http://www.phystech.com/download/ubench.html
    +FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    +Ubench Single CPU:   672792 (0.40s)
    +Ubench Single MEM:   852757 (0.48s)
    +-----------------------------------
    +Ubench Single AVG:   762774
     

    Wow, the CPU in the VM was a tiny bit faster than on the host! So this was probably just a glitch in the matrix. Memory seems slower, though.
    @@ -549,24 +549,24 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@freebsd:~ # ubench
    -Unix Benchmark Utility v.0.3
    -Copyright (C) July, 1999 PhysTech, Inc.
    -Author: Sergei Viznyuk <sv@phystech.com>
    -http://www.phystech.com/download/ubench.html
    -FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    -Ubench CPU:  2652857
    -swap_pager: out of swap space
    -swp_pager_getswapspace(27): failed
    -swap_pager: out of swap space
    -swp_pager_getswapspace(18): failed
    -Apr  4 23:02:43 freebsd kernel: pid 862 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    -swp_pager_getswapspace(6): failed
    -Apr  4 23:02:46 freebsd kernel: pid 863 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    -Apr  4 23:02:47 freebsd kernel: pid 864 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    -Apr  4 23:02:48 freebsd kernel: pid 865 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    -Apr  4 23:02:49 freebsd kernel: pid 861 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    -Apr  4 23:02:51 freebsd kernel: pid 839 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +
    root@freebsd:~ # ubench
    +Unix Benchmark Utility v.0.3
    +Copyright (C) July, 1999 PhysTech, Inc.
    +Author: Sergei Viznyuk <sv@phystech.com>
    +http://www.phystech.com/download/ubench.html
    +FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    +Ubench CPU:  2652857
    +swap_pager: out of swap space
    +swp_pager_getswapspace(27): failed
    +swap_pager: out of swap space
    +swp_pager_getswapspace(18): failed
    +Apr  4 23:02:43 freebsd kernel: pid 862 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +swp_pager_getswapspace(6): failed
    +Apr  4 23:02:46 freebsd kernel: pid 863 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +Apr  4 23:02:47 freebsd kernel: pid 864 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +Apr  4 23:02:48 freebsd kernel: pid 865 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +Apr  4 23:02:49 freebsd kernel: pid 861 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +Apr  4 23:02:51 freebsd kernel: pid 839 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
     

    The multi-CPU benchmark in the Bhyve VM ran with almost identical results to the FreeBSD host system. However, the memory benchmark failed with out-of-swap space errors. I am unsure why, as the VM has 14GB RAM, but I am not investigating further.
    diff --git a/gemfeed/2025-05-02-terminal-multiplexing-with-tmux-fish-edition.html b/gemfeed/2025-05-02-terminal-multiplexing-with-tmux-fish-edition.html index f2aa7b97..74d97695 100644 --- a/gemfeed/2025-05-02-terminal-multiplexing-with-tmux-fish-edition.html +++ b/gemfeed/2025-05-02-terminal-multiplexing-with-tmux-fish-edition.html @@ -192,14 +192,14 @@ set-option -g prefix C-g by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    function tmux::search
    -    set -l session (tmux list-sessions | fzf | cut -d: -f1)
    -    if test -z "$TMUX"
    -        tmux attach-session -t $session
    -    else
    -        tmux switch -t $session
    -    end
    -end
    +
    function tmux::search
    +    set -l session (tmux list-sessions | fzf | cut -d: -f1)
    +    if test -z "$TMUX"
    +        tmux attach-session -t $session
    +    else
    +        tmux switch -t $session
    +    end
    +end
     

    All it does is list all currently open sessions in fzf, where one of them can be searched and selected through fuzzy find, and then either switch (if already inside a session) to the other session or attach to the other session (if not yet in Tmux).
    diff --git a/gemfeed/2025-05-11-f3s-kubernetes-with-freebsd-part-5.html b/gemfeed/2025-05-11-f3s-kubernetes-with-freebsd-part-5.html index 6ba36119..9eeb5457 100644 --- a/gemfeed/2025-05-11-f3s-kubernetes-with-freebsd-part-5.html +++ b/gemfeed/2025-05-11-f3s-kubernetes-with-freebsd-part-5.html @@ -118,14 +118,14 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas freebsd-update fetch
    -paul@f0:~ % doas freebsd-update install
    -paul@f0:~ % doas shutdown -r now
    -..
    -..
    -paul@f0:~ % doas pkg update
    -paul@f0:~ % doas pkg upgrade
    -paul@f0:~ % reboot
    +
    paul@f0:~ % doas freebsd-update fetch
    +paul@f0:~ % doas freebsd-update install
    +paul@f0:~ % doas shutdown -r now
    +..
    +..
    +paul@f0:~ % doas pkg update
    +paul@f0:~ % doas pkg upgrade
    +paul@f0:~ % reboot
     

    Next, we install wireguard-tools and configure the WireGuard service:
    @@ -134,19 +134,19 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas pkg install wireguard-tools
    -paul@f0:~ % doas sysrc wireguard_interfaces=wg0
    -wireguard_interfaces:  -> wg0
    -paul@f0:~ % doas sysrc wireguard_enable=YES
    -wireguard_enable:  -> YES
    -paul@f0:~ % doas mkdir -p /usr/local/etc/wireguard
    -paul@f0:~ % doas touch /usr/local/etc/wireguard/wg0.conf
    -paul@f0:~ % doas service wireguard start
    -paul@f0:~ % doas wg show
    -interface: wg0
    -  public key: L+V9o0fNYkMVKNqsX7spBzD/9oSvxM/C7ZCZX1jLO3Q=
    -  private key: (hidden)
    -  listening port: 20246
    +
    paul@f0:~ % doas pkg install wireguard-tools
    +paul@f0:~ % doas sysrc wireguard_interfaces=wg0
    +wireguard_interfaces:  -> wg0
    +paul@f0:~ % doas sysrc wireguard_enable=YES
    +wireguard_enable:  -> YES
    +paul@f0:~ % doas mkdir -p /usr/local/etc/wireguard
    +paul@f0:~ % doas touch /usr/local/etc/wireguard/wg0.conf
    +paul@f0:~ % doas service wireguard start
    +paul@f0:~ % doas wg show
    +interface: wg0
    +  public key: L+V9o0fNYkMVKNqsX7spBzD/9oSvxM/C7ZCZX1jLO3Q=
    +  private key: (hidden)
    +  listening port: 20246
     

    We now have the WireGuard up and running, but it is not yet in any functional configuration. We will come back to that later.
    @@ -157,23 +157,23 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % cat <<END | doas tee -a /etc/hosts
    +
    paul@f0:~ % cat <<END | doas tee -a /etc/hosts
     
    -192.168.1.120 r0 r0.lan r0.lan.buetow.org
    -192.168.1.121 r1 r1.lan r1.lan.buetow.org
    -192.168.1.122 r2 r2.lan r2.lan.buetow.org
    +192.168.1.120 r0 r0.lan r0.lan.buetow.org
    +192.168.1.121 r1 r1.lan r1.lan.buetow.org
    +192.168.1.122 r2 r2.lan r2.lan.buetow.org
     
    -192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    -192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    -192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
    +192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    +192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    +192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
     
    -192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    -192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    -192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
    +192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    +192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    +192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
     
    -192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    -192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    -END
    +192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    +192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    +END
     

    As you can see, 192.168.1.0/24 is the network used in my LAN (with the fN and rN hosts) and 192.168.2.0/24 is the network used for the WireGuard mesh network. The wg0 interface will be used for all WireGuard traffic.
    @@ -186,8 +186,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] dnf update -y
    -[root@r0 ~] reboot
    +
    [root@r0 ~] dnf update -y
    +[root@r0 ~] reboot
     

    Next, we prepare WireGuard on them. Same as on the FreeBSD hosts, we will only prepare WireGuard without any useful configuration yet:
    @@ -196,12 +196,12 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] dnf install -y wireguard-tools
    -[root@r0 ~] mkdir -p /etc/wireguard
    -[root@r0 ~] touch /etc/wireguard/wg0.conf
    -[root@r0 ~] systemctl enable wg-quick@wg0.service
    -[root@r0 ~] systemctl start wg-quick@wg0.service
    -[root@r0 ~] systemctl disable firewalld
    +
    [root@r0 ~] dnf install -y wireguard-tools
    +[root@r0 ~] mkdir -p /etc/wireguard
    +[root@r0 ~] touch /etc/wireguard/wg0.conf
    +[root@r0 ~] systemctl enable wg-quick@wg0.service
    +[root@r0 ~] systemctl start wg-quick@wg0.service
    +[root@r0 ~] systemctl disable firewalld
     

    We also update the hosts file accordingly:
    @@ -210,23 +210,23 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] cat <<END >>/etc/hosts
    +
    [root@r0 ~] cat <<END >>/etc/hosts
     
    -192.168.1.130 f0 f0.lan f0.lan.buetow.org
    -192.168.1.131 f1 f1.lan f1.lan.buetow.org
    -192.168.1.132 f2 f2.lan f2.lan.buetow.org
    +192.168.1.130 f0 f0.lan f0.lan.buetow.org
    +192.168.1.131 f1 f1.lan f1.lan.buetow.org
    +192.168.1.132 f2 f2.lan f2.lan.buetow.org
     
    -192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    -192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    -192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
    +192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    +192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    +192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
     
    -192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    -192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    -192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
    +192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    +192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    +192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
     
    -192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    -192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    -END
    +192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    +192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    +END
     

    Unfortunately, the SELinux policy on Rocky Linux blocks WireGuard's operation. By making the wireguard_t domain permissive using semanage permissive -a wireguard_t, SELinux will no longer enforce restrictions for WireGuard, allowing it to work as intended:
    @@ -235,9 +235,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] dnf install -y policycoreutils-python-utils
    -[root@r0 ~] semanage permissive -a wireguard_t
    -[root@r0 ~] reboot
    +
    [root@r0 ~] dnf install -y policycoreutils-python-utils
    +[root@r0 ~] semanage permissive -a wireguard_t
    +[root@r0 ~] reboot
     

    https://github.com/angristan/wireguard-install/discussions/499
    @@ -250,14 +250,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    blowfish$ doas pkg_add wireguard-tools
    -blowfish$ doas mkdir /etc/wireguard
    -blowfish$ doas touch /etc/wireguard/wg0.conf
    -blowsish$ cat <<END | doas tee /etc/hostname.wg0
    -inet 192.168.2.110 255.255.255.0 NONE
    -up
    -!/usr/local/bin/wg setconf wg0 /etc/wireguard/wg0.conf
    -END
    +
    blowfish$ doas pkg_add wireguard-tools
    +blowfish$ doas mkdir /etc/wireguard
    +blowfish$ doas touch /etc/wireguard/wg0.conf
    +blowsish$ cat <<END | doas tee /etc/hostname.wg0
    +inet 192.168.2.110 255.255.255.0 NONE
    +up
    +!/usr/local/bin/wg setconf wg0 /etc/wireguard/wg0.conf
    +END
     

    Note that on blowfish, we configure 192.168.2.110 here in the hostname.wg, and on fishfinger, we configure 192.168.2.111. Those are the IP addresses of the WireGuard interfaces on those hosts.
    @@ -268,19 +268,19 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    blowfish$ cat <<END | doas tee -a /etc/hosts
    +
    blowfish$ cat <<END | doas tee -a /etc/hosts
     
    -192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    -192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    -192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
    +192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    +192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    +192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
     
    -192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    -192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    -192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
    +192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    +192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    +192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
     
    -192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    -192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    -END
    +192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    +192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    +END
     

    WireGuard configuration


    @@ -405,10 +405,10 @@ PersistentKeepalive = 25 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    > git clone https://codeberg.org/snonux/wireguardmeshgenerator
    -> cd ./wireguardmeshgenerator
    -> bundle install
    -> sudo dnf install -y wireguard-tools
    +
    > git clone https://codeberg.org/snonux/wireguardmeshgenerator
    +> cd ./wireguardmeshgenerator
    +> bundle install
    +> sudo dnf install -y wireguard-tools
     

    This assumes that Ruby and the bundler gem are already installed. If not, refer to the docs of your distribution.
    @@ -544,39 +544,39 @@ hosts: by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    begin
    -  options = { hosts: [] }
    -  OptionParser.new do |opts|
    -    opts.banner = 'Usage: wireguardmeshgenerator.rb [options]'
    -    opts.on('--generate', 'Generate Wireguard configs') do
    -      options[:generate] = true
    -    end
    -    opts.on('--install', 'Install Wireguard configs') do
    -      options[:install] = true
    -    end
    -    opts.on('--clean', 'Clean Wireguard configs') do
    -      options[:clean] = true
    -    end
    -    opts.on('--hosts=HOSTS', 'Comma separated hosts to configure') do |hosts|
    -      options[:hosts] = hosts.split(',')
    -    end
    -  end.parse!
    +
    begin
    +  options = { hosts: [] }
    +  OptionParser.new do |opts|
    +    opts.banner = 'Usage: wireguardmeshgenerator.rb [options]'
    +    opts.on('--generate', 'Generate Wireguard configs') do
    +      options[:generate] = true
    +    end
    +    opts.on('--install', 'Install Wireguard configs') do
    +      options[:install] = true
    +    end
    +    opts.on('--clean', 'Clean Wireguard configs') do
    +      options[:clean] = true
    +    end
    +    opts.on('--hosts=HOSTS', 'Comma separated hosts to configure') do |hosts|
    +      options[:hosts] = hosts.split(',')
    +    end
    +  end.parse!
     
    -  conf = YAML.load_file('wireguardmeshgenerator.yaml').freeze
    -  conf['hosts'].keys.select { options[:hosts].empty? || options[:hosts].include?(_1) }
    -               .each do |host|
    -    # Generate Wireguard configuration for the host reload!
    -    WireguardConfig.new(host, conf['hosts']).generate! if options[:generate]
    -    # Install Wireguard configuration for the host.
    -    InstallConfig.new(host, conf['hosts']).upload!.install!.reload! if options[:install]
    -    # Clean Wireguard configuration for the host.
    -    WireguardConfig.new(host, conf['hosts']).clean! if options[:clean]
    -  end
    -rescue StandardError => e
    -  puts "Error: #{e.message}"
    -  puts e.backtrace.join("\n")
    -  exit 2
    -end
    +  conf = YAML.load_file('wireguardmeshgenerator.yaml').freeze
    +  conf['hosts'].keys.select { options[:hosts].empty? || options[:hosts].include?(_1) }
    +               .each do |host|
    +    # Generate Wireguard configuration for the host reload!
    +    WireguardConfig.new(host, conf['hosts']).generate! if options[:generate]
    +    # Install Wireguard configuration for the host.
    +    InstallConfig.new(host, conf['hosts']).upload!.install!.reload! if options[:install]
    +    # Clean Wireguard configuration for the host.
    +    WireguardConfig.new(host, conf['hosts']).clean! if options[:clean]
    +  end
    +rescue StandardError => e
    +  puts "Error: #{e.message}"
    +  puts e.backtrace.join("\n")
    +  exit 2
    +end
     

    And we also have a Rakefile:
    @@ -585,19 +585,19 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    task :generate do
    -  ruby 'wireguardmeshgenerator.rb', '--generate'
    -end
    +
    task :generate do
    +  ruby 'wireguardmeshgenerator.rb', '--generate'
    +end
     
    -task :clean do
    -  ruby 'wireguardmeshgenerator.rb', '--clean'
    -end
    +task :clean do
    +  ruby 'wireguardmeshgenerator.rb', '--clean'
    +end
     
    -task :install do
    -  ruby 'wireguardmeshgenerator.rb', '--install'
    -end
    +task :install do
    +  ruby 'wireguardmeshgenerator.rb', '--install'
    +end
     
    -task default: :generate
    +task default: :generate
     


    @@ -611,16 +611,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    > rake generate
    -/usr/bin/ruby wireguardmeshgenerator.rb --generate
    -Generating dist/f0/etc/wireguard/wg0.conf
    -Generating dist/f1/etc/wireguard/wg0.conf
    -Generating dist/f2/etc/wireguard/wg0.conf
    -Generating dist/r0/etc/wireguard/wg0.conf
    -Generating dist/r1/etc/wireguard/wg0.conf
    -Generating dist/r2/etc/wireguard/wg0.conf
    -Generating dist/blowfish/etc/wireguard/wg0.conf
    -Generating dist/fishfinger/etc/wireguard/wg0.conf
    +
    > rake generate
    +/usr/bin/ruby wireguardmeshgenerator.rb --generate
    +Generating dist/f0/etc/wireguard/wg0.conf
    +Generating dist/f1/etc/wireguard/wg0.conf
    +Generating dist/f2/etc/wireguard/wg0.conf
    +Generating dist/r0/etc/wireguard/wg0.conf
    +Generating dist/r1/etc/wireguard/wg0.conf
    +Generating dist/r2/etc/wireguard/wg0.conf
    +Generating dist/blowfish/etc/wireguard/wg0.conf
    +Generating dist/fishfinger/etc/wireguard/wg0.conf
     

    It generated all the wg0.conf files listed in the output, plus those keys:
    @@ -629,51 +629,51 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    > find keys/ -type f
    -keys/f0/priv.key
    -keys/f0/pub.key
    -keys/psk/f0_f1.key
    -keys/psk/f0_f2.key
    -keys/psk/f0_r0.key
    -keys/psk/f0_r1.key
    -keys/psk/f0_r2.key
    -keys/psk/blowfish_f0.key
    -keys/psk/f0_fishfinger.key
    -keys/psk/f1_f2.key
    -keys/psk/f1_r0.key
    -keys/psk/f1_r1.key
    -keys/psk/f1_r2.key
    -keys/psk/blowfish_f1.key
    -keys/psk/f1_fishfinger.key
    -keys/psk/f2_r0.key
    -keys/psk/f2_r1.key
    -keys/psk/f2_r2.key
    -keys/psk/blowfish_f2.key
    -keys/psk/f2_fishfinger.key
    -keys/psk/r0_r1.key
    -keys/psk/r0_r2.key
    -keys/psk/blowfish_r0.key
    -keys/psk/fishfinger_r0.key
    -keys/psk/r1_r2.key
    -keys/psk/blowfish_r1.key
    -keys/psk/fishfinger_r1.key
    -keys/psk/blowfish_r2.key
    -keys/psk/fishfinger_r2.key
    -keys/psk/blowfish_fishfinger.key
    -keys/f1/priv.key
    -keys/f1/pub.key
    -keys/f2/priv.key
    -keys/f2/pub.key
    -keys/r0/priv.key
    -keys/r0/pub.key
    -keys/r1/priv.key
    -keys/r1/pub.key
    -keys/r2/priv.key
    -keys/r2/pub.key
    -keys/blowfish/priv.key
    -keys/blowfish/pub.key
    -keys/fishfinger/priv.key
    -keys/fishfinger/pub.key
    +
    > find keys/ -type f
    +keys/f0/priv.key
    +keys/f0/pub.key
    +keys/psk/f0_f1.key
    +keys/psk/f0_f2.key
    +keys/psk/f0_r0.key
    +keys/psk/f0_r1.key
    +keys/psk/f0_r2.key
    +keys/psk/blowfish_f0.key
    +keys/psk/f0_fishfinger.key
    +keys/psk/f1_f2.key
    +keys/psk/f1_r0.key
    +keys/psk/f1_r1.key
    +keys/psk/f1_r2.key
    +keys/psk/blowfish_f1.key
    +keys/psk/f1_fishfinger.key
    +keys/psk/f2_r0.key
    +keys/psk/f2_r1.key
    +keys/psk/f2_r2.key
    +keys/psk/blowfish_f2.key
    +keys/psk/f2_fishfinger.key
    +keys/psk/r0_r1.key
    +keys/psk/r0_r2.key
    +keys/psk/blowfish_r0.key
    +keys/psk/fishfinger_r0.key
    +keys/psk/r1_r2.key
    +keys/psk/blowfish_r1.key
    +keys/psk/fishfinger_r1.key
    +keys/psk/blowfish_r2.key
    +keys/psk/fishfinger_r2.key
    +keys/psk/blowfish_fishfinger.key
    +keys/f1/priv.key
    +keys/f1/pub.key
    +keys/f2/priv.key
    +keys/f2/pub.key
    +keys/r0/priv.key
    +keys/r0/pub.key
    +keys/r1/priv.key
    +keys/r1/pub.key
    +keys/r2/priv.key
    +keys/r2/pub.key
    +keys/blowfish/priv.key
    +keys/blowfish/pub.key
    +keys/fishfinger/priv.key
    +keys/fishfinger/pub.key
     

    Those keys are embedded in the resulting wg0.conf, so later, we only need to install the wg0.conf files and not all the keys individually.
    @@ -686,112 +686,112 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    > rake install
    -/usr/bin/ruby wireguardmeshgenerator.rb --install
    -Uploading dist/f0/etc/wireguard/wg0.conf to f0.lan.buetow.org:.
    -Installing Wireguard config on f0
    -Uploading cmd.sh to f0.lan.buetow.org:.
    -+ [ ! -d /usr/local/etc/wireguard ]
    -+ doas chmod 700 /usr/local/etc/wireguard
    -+ doas mv -v wg0.conf /usr/local/etc/wireguard
    -wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    -+ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on f0
    -Uploading cmd.sh to f0.lan.buetow.org:.
    -+ doas service wireguard reload
    -+ rm cmd.sh
    -Uploading dist/f1/etc/wireguard/wg0.conf to f1.lan.buetow.org:.
    -Installing Wireguard config on f1
    -Uploading cmd.sh to f1.lan.buetow.org:.
    -+ [ ! -d /usr/local/etc/wireguard ]
    -+ doas chmod 700 /usr/local/etc/wireguard
    -+ doas mv -v wg0.conf /usr/local/etc/wireguard
    -wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    -+ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on f1
    -Uploading cmd.sh to f1.lan.buetow.org:.
    -+ doas service wireguard reload
    -+ rm cmd.sh
    -Uploading dist/f2/etc/wireguard/wg0.conf to f2.lan.buetow.org:.
    -Installing Wireguard config on f2
    -Uploading cmd.sh to f2.lan.buetow.org:.
    -+ [ ! -d /usr/local/etc/wireguard ]
    -+ doas chmod 700 /usr/local/etc/wireguard
    -+ doas mv -v wg0.conf /usr/local/etc/wireguard
    -wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    -+ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on f2
    -Uploading cmd.sh to f2.lan.buetow.org:.
    -+ doas service wireguard reload
    -+ rm cmd.sh
    -Uploading dist/r0/etc/wireguard/wg0.conf to r0.lan.buetow.org:.
    -Installing Wireguard config on r0
    -Uploading cmd.sh to r0.lan.buetow.org:.
    -+ '[' '!' -d /etc/wireguard ']'
    -+ chmod 700 /etc/wireguard
    -+ mv -v wg0.conf /etc/wireguard
    -renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    -+ chmod 644 /etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on r0
    -Uploading cmd.sh to r0.lan.buetow.org:.
    -+ systemctl reload wg-quick@wg0.service
    -+ rm cmd.sh
    -Uploading dist/r1/etc/wireguard/wg0.conf to r1.lan.buetow.org:.
    -Installing Wireguard config on r1
    -Uploading cmd.sh to r1.lan.buetow.org:.
    -+ '[' '!' -d /etc/wireguard ']'
    -+ chmod 700 /etc/wireguard
    -+ mv -v wg0.conf /etc/wireguard
    -renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    -+ chmod 644 /etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on r1
    -Uploading cmd.sh to r1.lan.buetow.org:.
    -+ systemctl reload wg-quick@wg0.service
    -+ rm cmd.sh
    -Uploading dist/r2/etc/wireguard/wg0.conf to r2.lan.buetow.org:.
    -Installing Wireguard config on r2
    -Uploading cmd.sh to r2.lan.buetow.org:.
    -+ '[' '!' -d /etc/wireguard ']'
    -+ chmod 700 /etc/wireguard
    -+ mv -v wg0.conf /etc/wireguard
    -renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    -+ chmod 644 /etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on r2
    -Uploading cmd.sh to r2.lan.buetow.org:.
    -+ systemctl reload wg-quick@wg0.service
    -+ rm cmd.sh
    -Uploading dist/blowfish/etc/wireguard/wg0.conf to blowfish.buetow.org:.
    -Installing Wireguard config on blowfish
    -Uploading cmd.sh to blowfish.buetow.org:.
    -+ [ ! -d /etc/wireguard ]
    -+ doas chmod 700 /etc/wireguard
    -+ doas mv -v wg0.conf /etc/wireguard
    -wg0.conf -> /etc/wireguard/wg0.conf
    -+ doas chmod 644 /etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on blowfish
    -Uploading cmd.sh to blowfish.buetow.org:.
    -+ doas sh /etc/netstart wg0
    -+ rm cmd.sh
    -Uploading dist/fishfinger/etc/wireguard/wg0.conf to fishfinger.buetow.org:.
    -Installing Wireguard config on fishfinger
    -Uploading cmd.sh to fishfinger.buetow.org:.
    -+ [ ! -d /etc/wireguard ]
    -+ doas chmod 700 /etc/wireguard
    -+ doas mv -v wg0.conf /etc/wireguard
    -wg0.conf -> /etc/wireguard/wg0.conf
    -+ doas chmod 644 /etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on fishfinger
    -Uploading cmd.sh to fishfinger.buetow.org:.
    -+ doas sh /etc/netstart wg0
    -+ rm cmd.sh
    +
    > rake install
    +/usr/bin/ruby wireguardmeshgenerator.rb --install
    +Uploading dist/f0/etc/wireguard/wg0.conf to f0.lan.buetow.org:.
    +Installing Wireguard config on f0
    +Uploading cmd.sh to f0.lan.buetow.org:.
    ++ [ ! -d /usr/local/etc/wireguard ]
    ++ doas chmod 700 /usr/local/etc/wireguard
    ++ doas mv -v wg0.conf /usr/local/etc/wireguard
    +wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    ++ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on f0
    +Uploading cmd.sh to f0.lan.buetow.org:.
    ++ doas service wireguard reload
    ++ rm cmd.sh
    +Uploading dist/f1/etc/wireguard/wg0.conf to f1.lan.buetow.org:.
    +Installing Wireguard config on f1
    +Uploading cmd.sh to f1.lan.buetow.org:.
    ++ [ ! -d /usr/local/etc/wireguard ]
    ++ doas chmod 700 /usr/local/etc/wireguard
    ++ doas mv -v wg0.conf /usr/local/etc/wireguard
    +wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    ++ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on f1
    +Uploading cmd.sh to f1.lan.buetow.org:.
    ++ doas service wireguard reload
    ++ rm cmd.sh
    +Uploading dist/f2/etc/wireguard/wg0.conf to f2.lan.buetow.org:.
    +Installing Wireguard config on f2
    +Uploading cmd.sh to f2.lan.buetow.org:.
    ++ [ ! -d /usr/local/etc/wireguard ]
    ++ doas chmod 700 /usr/local/etc/wireguard
    ++ doas mv -v wg0.conf /usr/local/etc/wireguard
    +wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    ++ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on f2
    +Uploading cmd.sh to f2.lan.buetow.org:.
    ++ doas service wireguard reload
    ++ rm cmd.sh
    +Uploading dist/r0/etc/wireguard/wg0.conf to r0.lan.buetow.org:.
    +Installing Wireguard config on r0
    +Uploading cmd.sh to r0.lan.buetow.org:.
    ++ '[' '!' -d /etc/wireguard ']'
    ++ chmod 700 /etc/wireguard
    ++ mv -v wg0.conf /etc/wireguard
    +renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    ++ chmod 644 /etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on r0
    +Uploading cmd.sh to r0.lan.buetow.org:.
    ++ systemctl reload wg-quick@wg0.service
    ++ rm cmd.sh
    +Uploading dist/r1/etc/wireguard/wg0.conf to r1.lan.buetow.org:.
    +Installing Wireguard config on r1
    +Uploading cmd.sh to r1.lan.buetow.org:.
    ++ '[' '!' -d /etc/wireguard ']'
    ++ chmod 700 /etc/wireguard
    ++ mv -v wg0.conf /etc/wireguard
    +renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    ++ chmod 644 /etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on r1
    +Uploading cmd.sh to r1.lan.buetow.org:.
    ++ systemctl reload wg-quick@wg0.service
    ++ rm cmd.sh
    +Uploading dist/r2/etc/wireguard/wg0.conf to r2.lan.buetow.org:.
    +Installing Wireguard config on r2
    +Uploading cmd.sh to r2.lan.buetow.org:.
    ++ '[' '!' -d /etc/wireguard ']'
    ++ chmod 700 /etc/wireguard
    ++ mv -v wg0.conf /etc/wireguard
    +renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    ++ chmod 644 /etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on r2
    +Uploading cmd.sh to r2.lan.buetow.org:.
    ++ systemctl reload wg-quick@wg0.service
    ++ rm cmd.sh
    +Uploading dist/blowfish/etc/wireguard/wg0.conf to blowfish.buetow.org:.
    +Installing Wireguard config on blowfish
    +Uploading cmd.sh to blowfish.buetow.org:.
    ++ [ ! -d /etc/wireguard ]
    ++ doas chmod 700 /etc/wireguard
    ++ doas mv -v wg0.conf /etc/wireguard
    +wg0.conf -> /etc/wireguard/wg0.conf
    ++ doas chmod 644 /etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on blowfish
    +Uploading cmd.sh to blowfish.buetow.org:.
    ++ doas sh /etc/netstart wg0
    ++ rm cmd.sh
    +Uploading dist/fishfinger/etc/wireguard/wg0.conf to fishfinger.buetow.org:.
    +Installing Wireguard config on fishfinger
    +Uploading cmd.sh to fishfinger.buetow.org:.
    ++ [ ! -d /etc/wireguard ]
    ++ doas chmod 700 /etc/wireguard
    ++ doas mv -v wg0.conf /etc/wireguard
    +wg0.conf -> /etc/wireguard/wg0.conf
    ++ doas chmod 644 /etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on fishfinger
    +Uploading cmd.sh to fishfinger.buetow.org:.
    ++ doas sh /etc/netstart wg0
    ++ rm cmd.sh
     

    Re-generating mesh and installing the wg0.conf files again


    @@ -802,9 +802,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    > rake clean
    -> rake generate
    -> rake install
    +
    > rake clean
    +> rake generate
    +> rake install
     

    That would also delete and re-generate all the keys involved.
    @@ -817,52 +817,52 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas wg show
    -interface: wg0
    -  public key: Jm6YItMt94++dIeOyVi1I9AhNt2qQcryxCZezoX7X2Y=
    -  private key: (hidden)
    -  listening port: 56709
    +
    paul@f0:~ % doas wg show
    +interface: wg0
    +  public key: Jm6YItMt94++dIeOyVi1I9AhNt2qQcryxCZezoX7X2Y=
    +  private key: (hidden)
    +  listening port: 56709
     
    -peer: 8PvGZH1NohHpZPVJyjhctBX9xblsNvYBhpg68FsFcns=
    -  preshared key: (hidden)
    -  endpoint: 46.23.94.99:56709
    -  allowed ips: 192.168.2.111/32
    -  latest handshake: 1 minute, 46 seconds ago
    -  transfer: 124 B received, 1.75 KiB sent
    -  persistent keepalive: every 25 seconds
    +peer: 8PvGZH1NohHpZPVJyjhctBX9xblsNvYBhpg68FsFcns=
    +  preshared key: (hidden)
    +  endpoint: 46.23.94.99:56709
    +  allowed ips: 192.168.2.111/32
    +  latest handshake: 1 minute, 46 seconds ago
    +  transfer: 124 B received, 1.75 KiB sent
    +  persistent keepalive: every 25 seconds
     
    -peer: Xow+d3qVXgUMk4pcRSQ6Fe+vhYBa3VDyHX/4jrGoKns=
    -  preshared key: (hidden)
    -  endpoint: 23.88.35.144:56709
    -  allowed ips: 192.168.2.110/32
    -  latest handshake: 1 minute, 52 seconds ago
    -  transfer: 124 B received, 1.60 KiB sent
    -  persistent keepalive: every 25 seconds
    +peer: Xow+d3qVXgUMk4pcRSQ6Fe+vhYBa3VDyHX/4jrGoKns=
    +  preshared key: (hidden)
    +  endpoint: 23.88.35.144:56709
    +  allowed ips: 192.168.2.110/32
    +  latest handshake: 1 minute, 52 seconds ago
    +  transfer: 124 B received, 1.60 KiB sent
    +  persistent keepalive: every 25 seconds
     
    -peer: s3e93XoY7dPUQgLiVO4d8x/SRCFgEew+/wP7+zwgehI=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.120:56709
    -  allowed ips: 192.168.2.120/32
    +peer: s3e93XoY7dPUQgLiVO4d8x/SRCFgEew+/wP7+zwgehI=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.120:56709
    +  allowed ips: 192.168.2.120/32
     
    -peer: 2htXdNcxzpI2FdPDJy4T4VGtm1wpMEQu1AkQHjNY6F8=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.131:56709
    -  allowed ips: 192.168.2.131/32
    +peer: 2htXdNcxzpI2FdPDJy4T4VGtm1wpMEQu1AkQHjNY6F8=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.131:56709
    +  allowed ips: 192.168.2.131/32
     
    -peer: 0Y/H20W8YIbF7DA1sMwMacLI8WS9yG+1/QO7m2oyllg=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.122:56709
    -  allowed ips: 192.168.2.122/32
    +peer: 0Y/H20W8YIbF7DA1sMwMacLI8WS9yG+1/QO7m2oyllg=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.122:56709
    +  allowed ips: 192.168.2.122/32
     
    -peer: Hhy9kMPOOjChXV2RA5WeCGs+J0FE3rcNPDw/TLSn7i8=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.121:56709
    -  allowed ips: 192.168.2.121/32
    +peer: Hhy9kMPOOjChXV2RA5WeCGs+J0FE3rcNPDw/TLSn7i8=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.121:56709
    +  allowed ips: 192.168.2.121/32
     
    -peer: SlGVsACE1wiaRoGvCR3f7AuHfRS+1jjhS+YwEJ2HvF0=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.132:56709
    -  allowed ips: 192.168.2.132/32
    +peer: SlGVsACE1wiaRoGvCR3f7AuHfRS+1jjhS+YwEJ2HvF0=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.132:56709
    +  allowed ips: 192.168.2.132/32
     

    All the hosts are pingable as well, e.g.:
    @@ -871,65 +871,65 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % foreach peer ( f1 f2 r0 r1 r2 blowfish fishfinger )
    -foreach? ping -c2 $peer.wg0
    -foreach? echo
    -foreach? end
    -PING f1.wg0 (192.168.2.131): 56 data bytes
    -64 bytes from 192.168.2.131: icmp_seq=0 ttl=64 time=0.334 ms
    -64 bytes from 192.168.2.131: icmp_seq=1 ttl=64 time=0.260 ms
    +
    paul@f0:~ % foreach peer ( f1 f2 r0 r1 r2 blowfish fishfinger )
    +foreach? ping -c2 $peer.wg0
    +foreach? echo
    +foreach? end
    +PING f1.wg0 (192.168.2.131): 56 data bytes
    +64 bytes from 192.168.2.131: icmp_seq=0 ttl=64 time=0.334 ms
    +64 bytes from 192.168.2.131: icmp_seq=1 ttl=64 time=0.260 ms
     
    ---- f1.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 0.260/0.297/0.334/0.037 ms
    +--- f1.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 0.260/0.297/0.334/0.037 ms
     
    -PING f2.wg0 (192.168.2.132): 56 data bytes
    -64 bytes from 192.168.2.132: icmp_seq=0 ttl=64 time=0.323 ms
    -64 bytes from 192.168.2.132: icmp_seq=1 ttl=64 time=0.303 ms
    +PING f2.wg0 (192.168.2.132): 56 data bytes
    +64 bytes from 192.168.2.132: icmp_seq=0 ttl=64 time=0.323 ms
    +64 bytes from 192.168.2.132: icmp_seq=1 ttl=64 time=0.303 ms
     
    ---- f2.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 0.303/0.313/0.323/0.010 ms
    +--- f2.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 0.303/0.313/0.323/0.010 ms
     
    -PING r0.wg0 (192.168.2.120): 56 data bytes
    -64 bytes from 192.168.2.120: icmp_seq=0 ttl=64 time=0.716 ms
    -64 bytes from 192.168.2.120: icmp_seq=1 ttl=64 time=0.406 ms
    +PING r0.wg0 (192.168.2.120): 56 data bytes
    +64 bytes from 192.168.2.120: icmp_seq=0 ttl=64 time=0.716 ms
    +64 bytes from 192.168.2.120: icmp_seq=1 ttl=64 time=0.406 ms
     
    ---- r0.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 0.406/0.561/0.716/0.155 ms
    +--- r0.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 0.406/0.561/0.716/0.155 ms
     
    -PING r1.wg0 (192.168.2.121): 56 data bytes
    -64 bytes from 192.168.2.121: icmp_seq=0 ttl=64 time=0.639 ms
    -64 bytes from 192.168.2.121: icmp_seq=1 ttl=64 time=0.629 ms
    +PING r1.wg0 (192.168.2.121): 56 data bytes
    +64 bytes from 192.168.2.121: icmp_seq=0 ttl=64 time=0.639 ms
    +64 bytes from 192.168.2.121: icmp_seq=1 ttl=64 time=0.629 ms
     
    ---- r1.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 0.629/0.634/0.639/0.005 ms
    +--- r1.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 0.629/0.634/0.639/0.005 ms
     
    -PING r2.wg0 (192.168.2.122): 56 data bytes
    -64 bytes from 192.168.2.122: icmp_seq=0 ttl=64 time=0.569 ms
    -64 bytes from 192.168.2.122: icmp_seq=1 ttl=64 time=0.479 ms
    +PING r2.wg0 (192.168.2.122): 56 data bytes
    +64 bytes from 192.168.2.122: icmp_seq=0 ttl=64 time=0.569 ms
    +64 bytes from 192.168.2.122: icmp_seq=1 ttl=64 time=0.479 ms
     
    ---- r2.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 0.479/0.524/0.569/0.045 ms
    +--- r2.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 0.479/0.524/0.569/0.045 ms
     
    -PING blowfish.wg0 (192.168.2.110): 56 data bytes
    -64 bytes from 192.168.2.110: icmp_seq=0 ttl=255 time=35.745 ms
    -64 bytes from 192.168.2.110: icmp_seq=1 ttl=255 time=35.481 ms
    +PING blowfish.wg0 (192.168.2.110): 56 data bytes
    +64 bytes from 192.168.2.110: icmp_seq=0 ttl=255 time=35.745 ms
    +64 bytes from 192.168.2.110: icmp_seq=1 ttl=255 time=35.481 ms
     
    ---- blowfish.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 35.481/35.613/35.745/0.132 ms
    +--- blowfish.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 35.481/35.613/35.745/0.132 ms
     
    -PING fishfinger.wg0 (192.168.2.111): 56 data bytes
    -64 bytes from 192.168.2.111: icmp_seq=0 ttl=255 time=33.992 ms
    -64 bytes from 192.168.2.111: icmp_seq=1 ttl=255 time=33.751 ms
    +PING fishfinger.wg0 (192.168.2.111): 56 data bytes
    +64 bytes from 192.168.2.111: icmp_seq=0 ttl=255 time=33.992 ms
    +64 bytes from 192.168.2.111: icmp_seq=1 ttl=255 time=33.751 ms
     
    ---- fishfinger.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 33.751/33.872/33.992/0.120 ms
    +--- fishfinger.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 33.751/33.872/33.992/0.120 ms
     

    Note that the loop above is a tcsh loop, the default shell used in FreeBSD. Of course, all other peers can ping their peers as well!
    @@ -940,60 +940,60 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas wg show
    -interface: wg0
    -  public key: Jm6YItMt94++dIeOyVi1I9AhNt2qQcryxCZezoX7X2Y=
    -  private key: (hidden)
    -  listening port: 56709
    +
    paul@f0:~ % doas wg show
    +interface: wg0
    +  public key: Jm6YItMt94++dIeOyVi1I9AhNt2qQcryxCZezoX7X2Y=
    +  private key: (hidden)
    +  listening port: 56709
     
    -peer: 0Y/H20W8YIbF7DA1sMwMacLI8WS9yG+1/QO7m2oyllg=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.122:56709
    -  allowed ips: 192.168.2.122/32
    -  latest handshake: 10 seconds ago
    -  transfer: 440 B received, 532 B sent
    +peer: 0Y/H20W8YIbF7DA1sMwMacLI8WS9yG+1/QO7m2oyllg=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.122:56709
    +  allowed ips: 192.168.2.122/32
    +  latest handshake: 10 seconds ago
    +  transfer: 440 B received, 532 B sent
     
    -peer: Hhy9kMPOOjChXV2RA5WeCGs+J0FE3rcNPDw/TLSn7i8=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.121:56709
    -  allowed ips: 192.168.2.121/32
    -  latest handshake: 12 seconds ago
    -  transfer: 440 B received, 564 B sent
    +peer: Hhy9kMPOOjChXV2RA5WeCGs+J0FE3rcNPDw/TLSn7i8=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.121:56709
    +  allowed ips: 192.168.2.121/32
    +  latest handshake: 12 seconds ago
    +  transfer: 440 B received, 564 B sent
     
    -peer: s3e93XoY7dPUQgLiVO4d8x/SRCFgEew+/wP7+zwgehI=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.120:56709
    -  allowed ips: 192.168.2.120/32
    -  latest handshake: 14 seconds ago
    -  transfer: 440 B received, 564 B sent
    +peer: s3e93XoY7dPUQgLiVO4d8x/SRCFgEew+/wP7+zwgehI=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.120:56709
    +  allowed ips: 192.168.2.120/32
    +  latest handshake: 14 seconds ago
    +  transfer: 440 B received, 564 B sent
     
    -peer: SlGVsACE1wiaRoGvCR3f7AuHfRS+1jjhS+YwEJ2HvF0=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.132:56709
    -  allowed ips: 192.168.2.132/32
    -  latest handshake: 17 seconds ago
    -  transfer: 472 B received, 564 B sent
    +peer: SlGVsACE1wiaRoGvCR3f7AuHfRS+1jjhS+YwEJ2HvF0=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.132:56709
    +  allowed ips: 192.168.2.132/32
    +  latest handshake: 17 seconds ago
    +  transfer: 472 B received, 564 B sent
     
    -peer: Xow+d3qVXgUMk4pcRSQ6Fe+vhYBa3VDyHX/4jrGoKns=
    -  preshared key: (hidden)
    -  endpoint: 23.88.35.144:56709
    -  allowed ips: 192.168.2.110/32
    -  latest handshake: 55 seconds ago
    -  transfer: 472 B received, 596 B sent
    -  persistent keepalive: every 25 seconds
    +peer: Xow+d3qVXgUMk4pcRSQ6Fe+vhYBa3VDyHX/4jrGoKns=
    +  preshared key: (hidden)
    +  endpoint: 23.88.35.144:56709
    +  allowed ips: 192.168.2.110/32
    +  latest handshake: 55 seconds ago
    +  transfer: 472 B received, 596 B sent
    +  persistent keepalive: every 25 seconds
     
    -peer: 8PvGZH1NohHpZPVJyjhctBX9xblsNvYBhpg68FsFcns=
    -  preshared key: (hidden)
    -  endpoint: 46.23.94.99:56709
    -  allowed ips: 192.168.2.111/32
    -  latest handshake: 55 seconds ago
    -  transfer: 472 B received, 596 B sent
    -  persistent keepalive: every 25 seconds
    +peer: 8PvGZH1NohHpZPVJyjhctBX9xblsNvYBhpg68FsFcns=
    +  preshared key: (hidden)
    +  endpoint: 46.23.94.99:56709
    +  allowed ips: 192.168.2.111/32
    +  latest handshake: 55 seconds ago
    +  transfer: 472 B received, 596 B sent
    +  persistent keepalive: every 25 seconds
     
    -peer: 2htXdNcxzpI2FdPDJy4T4VGtm1wpMEQu1AkQHjNY6F8=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.131:56709
    -  allowed ips: 192.168.2.131/32
    +peer: 2htXdNcxzpI2FdPDJy4T4VGtm1wpMEQu1AkQHjNY6F8=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.131:56709
    +  allowed ips: 192.168.2.131/32
     

    Conclusion


    diff --git a/gemfeed/DRAFT-f3s-kubernetes-with-freebsd-part-6.html b/gemfeed/DRAFT-f3s-kubernetes-with-freebsd-part-6.html index 5e94708d..3b880c29 100644 --- a/gemfeed/DRAFT-f3s-kubernetes-with-freebsd-part-6.html +++ b/gemfeed/DRAFT-f3s-kubernetes-with-freebsd-part-6.html @@ -67,21 +67,21 @@ paul@f1:/ % by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/ % doas newfs /dev/da0
    -/dev/da0: 15000.0MB (30720000 sectors) block size 32768, fragment size 4096
    -        using 24 cylinder groups of 625.22MB, 20007 blks, 80128 inodes.
    -        with soft updates
    -super-block backups (for fsck_ffs -b #) at:
    - 192, 1280640, 2561088, 3841536, 5121984, 6402432, 7682880, 8963328, 10243776,
    -11524224, 12804672, 14085120, 15365568, 16646016, 17926464, 19206912,k 20487360,
    -...
    +
    paul@f0:/ % doas newfs /dev/da0
    +/dev/da0: 15000.0MB (30720000 sectors) block size 32768, fragment size 4096
    +        using 24 cylinder groups of 625.22MB, 20007 blks, 80128 inodes.
    +        with soft updates
    +super-block backups (for fsck_ffs -b #) at:
    + 192, 1280640, 2561088, 3841536, 5121984, 6402432, 7682880, 8963328, 10243776,
    +11524224, 12804672, 14085120, 15365568, 16646016, 17926464, 19206912,k 20487360,
    +...
     
    -paul@f0:/ % echo '/dev/da0 /keys ufs rw 0 2' | doas tee -a /etc/fstab
    -/dev/da0 /keys ufs rw 0 2
    -paul@f0:/ % doas mkdir /keys
    -paul@f0:/ % doas mount /keys
    -paul@f0:/ % df | grep keys
    -/dev/da0             14877596       8  13687384     0%    /keys
    +paul@f0:/ % echo '/dev/da0 /keys ufs rw 0 2' | doas tee -a /etc/fstab
    +/dev/da0 /keys ufs rw 0 2
    +paul@f0:/ % doas mkdir /keys
    +paul@f0:/ % doas mount /keys
    +paul@f0:/ % df | grep keys
    +/dev/da0             14877596       8  13687384     0%    /keys
     

    Generating encryption keys


    @@ -112,17 +112,17 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/keys % doas zpool create -m /data zdata /dev/ada1
    -paul@f0:/keys % doas zfs create -o encryption=on -o keyformat=raw -o keylocation=file:///keys/`hostname`:zdata.key zdata/enc
    -paul@f0:/ % zfs list | grep zdata
    -zdata                                          836K   899G    96K  /data
    -zdata/enc                                      200K   899G   200K  /data/enc
    -paul@f0:/keys % zfs get all zdata/enc | grep -E -i '(encryption|key)'
    -zdata/enc  encryption            aes-256-gcm                               -
    -zdata/enc  keylocation           file:///keys/f0.lan.buetow.org:zdata.key  local
    -zdata/enc  keyformat             raw                                       -
    -zdata/enc  encryptionroot        zdata/enc                                 -
    -zdata/enc  keystatus             available                                 -
    +
    paul@f0:/keys % doas zpool create -m /data zdata /dev/ada1
    +paul@f0:/keys % doas zfs create -o encryption=on -o keyformat=raw -o keylocation=file:///keys/`hostname`:zdata.key zdata/enc
    +paul@f0:/ % zfs list | grep zdata
    +zdata                                          836K   899G    96K  /data
    +zdata/enc                                      200K   899G   200K  /data/enc
    +paul@f0:/keys % zfs get all zdata/enc | grep -E -i '(encryption|key)'
    +zdata/enc  encryption            aes-256-gcm                               -
    +zdata/enc  keylocation           file:///keys/f0.lan.buetow.org:zdata.key  local
    +zdata/enc  keyformat             raw                                       -
    +zdata/enc  encryptionroot        zdata/enc                                 -
    +zdata/enc  keystatus             available                                 -
     

    Migrating Bhyve VMs to encrypted bhyve ZFS volume


    @@ -133,60 +133,60 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/keys % doas vm stop rocky
    -Sending ACPI shutdown to rocky
    +
    paul@f0:/keys % doas vm stop rocky
    +Sending ACPI shutdown to rocky
     
    -paul@f0:/keys % doas vm list
    -NAME     DATASTORE  LOADER     CPU  MEMORY  VNC  AUTO     STATE
    -rocky    default    uefi       4    14G     -    Yes [1]  Stopped
    +paul@f0:/keys % doas vm list
    +NAME     DATASTORE  LOADER     CPU  MEMORY  VNC  AUTO     STATE
    +rocky    default    uefi       4    14G     -    Yes [1]  Stopped
     
     
    -paul@f0:/keys % doas zfs rename zroot/bhyve zroot/bhyve_old
    -paul@f0:/keys % doas zfs set mountpoint=/mnt zroot/bhyve_old
    -paul@f0:/keys % doas zfs snapshot zroot/bhyve_old/rocky@hamburger
    +paul@f0:/keys % doas zfs rename zroot/bhyve zroot/bhyve_old
    +paul@f0:/keys % doas zfs set mountpoint=/mnt zroot/bhyve_old
    +paul@f0:/keys % doas zfs snapshot zroot/bhyve_old/rocky@hamburger
     
     
    -paul@f0:/keys % doas zfs create -o encryption=on -o keyformat=raw -o keylocation=file:///keys/`hostname`:bhyve.key zroot/bhyve
    -paul@f0:/keys % doas zfs set mountpoint=/zroot/bhyve zroot/bhyve
    -paul@f0:/keys % doas zfs set mountpoint=/zroot/bhyve/rocky zroot/bhyve/rocky
    +paul@f0:/keys % doas zfs create -o encryption=on -o keyformat=raw -o keylocation=file:///keys/`hostname`:bhyve.key zroot/bhyve
    +paul@f0:/keys % doas zfs set mountpoint=/zroot/bhyve zroot/bhyve
    +paul@f0:/keys % doas zfs set mountpoint=/zroot/bhyve/rocky zroot/bhyve/rocky
     
    -paul@f0:/keys % doas zfs send zroot/bhyve_old/rocky@hamburger | doas zfs recv zroot/bhyve/rocky
    -paul@f0:/keys % doas cp -Rp /mnt/.config /zroot/bhyve/
    -paul@f0:/keys % doas cp -Rp /mnt/.img /zroot/bhyve/
    -paul@f0:/keys % doas cp -Rp /mnt/.templates /zroot/bhyve/
    -paul@f0:/keys % doas cp -Rp /mnt/.iso /zroot/bhyve/
    +paul@f0:/keys % doas zfs send zroot/bhyve_old/rocky@hamburger | doas zfs recv zroot/bhyve/rocky
    +paul@f0:/keys % doas cp -Rp /mnt/.config /zroot/bhyve/
    +paul@f0:/keys % doas cp -Rp /mnt/.img /zroot/bhyve/
    +paul@f0:/keys % doas cp -Rp /mnt/.templates /zroot/bhyve/
    +paul@f0:/keys % doas cp -Rp /mnt/.iso /zroot/bhyve/
     
    -paul@f0:/keys % doas sysrc zfskeys_enable=YES
    -zfskeys_enable:  -> YES
    -paul@f0:/keys % doas vm init
    -paul@f0:/keys % doas reboot
    -.
    -.
    -.
    -paul@f0:~ % doas vm list
    -paul@f0:~ % doas vm list
    -NAME     DATASTORE  LOADER     CPU  MEMORY  VNC           AUTO     STATE
    -rocky    default    uefi       4    14G     0.0.0.0:5900  Yes [1]  Running (2265)
    +paul@f0:/keys % doas sysrc zfskeys_enable=YES
    +zfskeys_enable:  -> YES
    +paul@f0:/keys % doas vm init
    +paul@f0:/keys % doas reboot
    +.
    +.
    +.
    +paul@f0:~ % doas vm list
    +paul@f0:~ % doas vm list
    +NAME     DATASTORE  LOADER     CPU  MEMORY  VNC           AUTO     STATE
    +rocky    default    uefi       4    14G     0.0.0.0:5900  Yes [1]  Running (2265)
     

    -
    paul@f0:~ % doas zfs destroy -R zroot/bhyve_old
    +
    paul@f0:~ % doas zfs destroy -R zroot/bhyve_old
     
    -paul@f0:~ % zfs get all zroot/bhyve | grep -E '(encryption|key)'
    -zroot/bhyve  encryption            aes-256-gcm                               -
    -zroot/bhyve  keylocation           file:///keys/f0.lan.buetow.org:bhyve.key  local
    -zroot/bhyve  keyformat             raw                                       -
    -zroot/bhyve  encryptionroot        zroot/bhyve                               -
    -zroot/bhyve  keystatus             available                                 -
    -paul@f0:~ % zfs get all zroot/bhyve/rocky | grep -E '(encryption|key)'
    -zroot/bhyve/rocky  encryption            aes-256-gcm            -
    -zroot/bhyve/rocky  keylocation           none                   default
    -zroot/bhyve/rocky  keyformat             raw                    -
    -zroot/bhyve/rocky  encryptionroot        zroot/bhyve            -
    -zroot/bhyve/rocky  keystatus             available              -
    +paul@f0:~ % zfs get all zroot/bhyve | grep -E '(encryption|key)'
    +zroot/bhyve  encryption            aes-256-gcm                               -
    +zroot/bhyve  keylocation           file:///keys/f0.lan.buetow.org:bhyve.key  local
    +zroot/bhyve  keyformat             raw                                       -
    +zroot/bhyve  encryptionroot        zroot/bhyve                               -
    +zroot/bhyve  keystatus             available                                 -
    +paul@f0:~ % zfs get all zroot/bhyve/rocky | grep -E '(encryption|key)'
    +zroot/bhyve/rocky  encryption            aes-256-gcm            -
    +zroot/bhyve/rocky  keylocation           none                   default
    +zroot/bhyve/rocky  keyformat             raw                    -
    +zroot/bhyve/rocky  encryptionroot        zroot/bhyve            -
    +zroot/bhyve/rocky  keystatus             available              -
     

    CARP


    diff --git a/gemfeed/atom.xml b/gemfeed/atom.xml index 00a46348..87e17fdd 100644 --- a/gemfeed/atom.xml +++ b/gemfeed/atom.xml @@ -1,6 +1,6 @@ - 2025-06-22T22:34:04+03:00 + 2025-06-22T23:02:51+03:00 foo.zone feed To be in the .zone! @@ -390,14 +390,14 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas freebsd-update fetch
    -paul@f0:~ % doas freebsd-update install
    -paul@f0:~ % doas shutdown -r now
    -..
    -..
    -paul@f0:~ % doas pkg update
    -paul@f0:~ % doas pkg upgrade
    -paul@f0:~ % reboot
    +
    paul@f0:~ % doas freebsd-update fetch
    +paul@f0:~ % doas freebsd-update install
    +paul@f0:~ % doas shutdown -r now
    +..
    +..
    +paul@f0:~ % doas pkg update
    +paul@f0:~ % doas pkg upgrade
    +paul@f0:~ % reboot
     

    Next, we install wireguard-tools and configure the WireGuard service:
    @@ -406,19 +406,19 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas pkg install wireguard-tools
    -paul@f0:~ % doas sysrc wireguard_interfaces=wg0
    -wireguard_interfaces:  -> wg0
    -paul@f0:~ % doas sysrc wireguard_enable=YES
    -wireguard_enable:  -> YES
    -paul@f0:~ % doas mkdir -p /usr/local/etc/wireguard
    -paul@f0:~ % doas touch /usr/local/etc/wireguard/wg0.conf
    -paul@f0:~ % doas service wireguard start
    -paul@f0:~ % doas wg show
    -interface: wg0
    -  public key: L+V9o0fNYkMVKNqsX7spBzD/9oSvxM/C7ZCZX1jLO3Q=
    -  private key: (hidden)
    -  listening port: 20246
    +
    paul@f0:~ % doas pkg install wireguard-tools
    +paul@f0:~ % doas sysrc wireguard_interfaces=wg0
    +wireguard_interfaces:  -> wg0
    +paul@f0:~ % doas sysrc wireguard_enable=YES
    +wireguard_enable:  -> YES
    +paul@f0:~ % doas mkdir -p /usr/local/etc/wireguard
    +paul@f0:~ % doas touch /usr/local/etc/wireguard/wg0.conf
    +paul@f0:~ % doas service wireguard start
    +paul@f0:~ % doas wg show
    +interface: wg0
    +  public key: L+V9o0fNYkMVKNqsX7spBzD/9oSvxM/C7ZCZX1jLO3Q=
    +  private key: (hidden)
    +  listening port: 20246
     

    We now have the WireGuard up and running, but it is not yet in any functional configuration. We will come back to that later.
    @@ -429,23 +429,23 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % cat <<END | doas tee -a /etc/hosts
    +
    paul@f0:~ % cat <<END | doas tee -a /etc/hosts
     
    -192.168.1.120 r0 r0.lan r0.lan.buetow.org
    -192.168.1.121 r1 r1.lan r1.lan.buetow.org
    -192.168.1.122 r2 r2.lan r2.lan.buetow.org
    +192.168.1.120 r0 r0.lan r0.lan.buetow.org
    +192.168.1.121 r1 r1.lan r1.lan.buetow.org
    +192.168.1.122 r2 r2.lan r2.lan.buetow.org
     
    -192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    -192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    -192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
    +192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    +192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    +192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
     
    -192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    -192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    -192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
    +192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    +192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    +192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
     
    -192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    -192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    -END
    +192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    +192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    +END
     

    As you can see, 192.168.1.0/24 is the network used in my LAN (with the fN and rN hosts) and 192.168.2.0/24 is the network used for the WireGuard mesh network. The wg0 interface will be used for all WireGuard traffic.
    @@ -458,8 +458,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] dnf update -y
    -[root@r0 ~] reboot
    +
    [root@r0 ~] dnf update -y
    +[root@r0 ~] reboot
     

    Next, we prepare WireGuard on them. Same as on the FreeBSD hosts, we will only prepare WireGuard without any useful configuration yet:
    @@ -468,12 +468,12 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] dnf install -y wireguard-tools
    -[root@r0 ~] mkdir -p /etc/wireguard
    -[root@r0 ~] touch /etc/wireguard/wg0.conf
    -[root@r0 ~] systemctl enable wg-quick@wg0.service
    -[root@r0 ~] systemctl start wg-quick@wg0.service
    -[root@r0 ~] systemctl disable firewalld
    +
    [root@r0 ~] dnf install -y wireguard-tools
    +[root@r0 ~] mkdir -p /etc/wireguard
    +[root@r0 ~] touch /etc/wireguard/wg0.conf
    +[root@r0 ~] systemctl enable wg-quick@wg0.service
    +[root@r0 ~] systemctl start wg-quick@wg0.service
    +[root@r0 ~] systemctl disable firewalld
     

    We also update the hosts file accordingly:
    @@ -482,23 +482,23 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] cat <<END >>/etc/hosts
    +
    [root@r0 ~] cat <<END >>/etc/hosts
     
    -192.168.1.130 f0 f0.lan f0.lan.buetow.org
    -192.168.1.131 f1 f1.lan f1.lan.buetow.org
    -192.168.1.132 f2 f2.lan f2.lan.buetow.org
    +192.168.1.130 f0 f0.lan f0.lan.buetow.org
    +192.168.1.131 f1 f1.lan f1.lan.buetow.org
    +192.168.1.132 f2 f2.lan f2.lan.buetow.org
     
    -192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    -192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    -192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
    +192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    +192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    +192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
     
    -192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    -192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    -192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
    +192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    +192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    +192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
     
    -192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    -192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    -END
    +192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    +192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    +END
     

    Unfortunately, the SELinux policy on Rocky Linux blocks WireGuard's operation. By making the wireguard_t domain permissive using semanage permissive -a wireguard_t, SELinux will no longer enforce restrictions for WireGuard, allowing it to work as intended:
    @@ -507,9 +507,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] dnf install -y policycoreutils-python-utils
    -[root@r0 ~] semanage permissive -a wireguard_t
    -[root@r0 ~] reboot
    +
    [root@r0 ~] dnf install -y policycoreutils-python-utils
    +[root@r0 ~] semanage permissive -a wireguard_t
    +[root@r0 ~] reboot
     

    https://github.com/angristan/wireguard-install/discussions/499
    @@ -522,14 +522,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    blowfish$ doas pkg_add wireguard-tools
    -blowfish$ doas mkdir /etc/wireguard
    -blowfish$ doas touch /etc/wireguard/wg0.conf
    -blowsish$ cat <<END | doas tee /etc/hostname.wg0
    -inet 192.168.2.110 255.255.255.0 NONE
    -up
    -!/usr/local/bin/wg setconf wg0 /etc/wireguard/wg0.conf
    -END
    +
    blowfish$ doas pkg_add wireguard-tools
    +blowfish$ doas mkdir /etc/wireguard
    +blowfish$ doas touch /etc/wireguard/wg0.conf
    +blowsish$ cat <<END | doas tee /etc/hostname.wg0
    +inet 192.168.2.110 255.255.255.0 NONE
    +up
    +!/usr/local/bin/wg setconf wg0 /etc/wireguard/wg0.conf
    +END
     

    Note that on blowfish, we configure 192.168.2.110 here in the hostname.wg, and on fishfinger, we configure 192.168.2.111. Those are the IP addresses of the WireGuard interfaces on those hosts.
    @@ -540,19 +540,19 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    blowfish$ cat <<END | doas tee -a /etc/hosts
    +
    blowfish$ cat <<END | doas tee -a /etc/hosts
     
    -192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    -192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    -192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
    +192.168.2.130 f0.wg0 f0.wg0.wan.buetow.org
    +192.168.2.131 f1.wg0 f1.wg0.wan.buetow.org
    +192.168.2.132 f2.wg0 f2.wg0.wan.buetow.org
     
    -192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    -192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    -192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
    +192.168.2.120 r0.wg0 r0.wg0.wan.buetow.org
    +192.168.2.121 r1.wg0 r1.wg0.wan.buetow.org
    +192.168.2.122 r2.wg0 r2.wg0.wan.buetow.org
     
    -192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    -192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    -END
    +192.168.2.110 blowfish.wg0 blowfish.wg0.wan.buetow.org
    +192.168.2.111 fishfinger.wg0 fishfinger.wg0.wan.buetow.org
    +END
     

    WireGuard configuration


    @@ -677,10 +677,10 @@ PersistentKeepalive = 25 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    > git clone https://codeberg.org/snonux/wireguardmeshgenerator
    -> cd ./wireguardmeshgenerator
    -> bundle install
    -> sudo dnf install -y wireguard-tools
    +
    > git clone https://codeberg.org/snonux/wireguardmeshgenerator
    +> cd ./wireguardmeshgenerator
    +> bundle install
    +> sudo dnf install -y wireguard-tools
     

    This assumes that Ruby and the bundler gem are already installed. If not, refer to the docs of your distribution.
    @@ -816,39 +816,39 @@ hosts: by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    begin
    -  options = { hosts: [] }
    -  OptionParser.new do |opts|
    -    opts.banner = 'Usage: wireguardmeshgenerator.rb [options]'
    -    opts.on('--generate', 'Generate Wireguard configs') do
    -      options[:generate] = true
    -    end
    -    opts.on('--install', 'Install Wireguard configs') do
    -      options[:install] = true
    -    end
    -    opts.on('--clean', 'Clean Wireguard configs') do
    -      options[:clean] = true
    -    end
    -    opts.on('--hosts=HOSTS', 'Comma separated hosts to configure') do |hosts|
    -      options[:hosts] = hosts.split(',')
    -    end
    -  end.parse!
    -
    -  conf = YAML.load_file('wireguardmeshgenerator.yaml').freeze
    -  conf['hosts'].keys.select { options[:hosts].empty? || options[:hosts].include?(_1) }
    -               .each do |host|
    -    # Generate Wireguard configuration for the host reload!
    -    WireguardConfig.new(host, conf['hosts']).generate! if options[:generate]
    -    # Install Wireguard configuration for the host.
    -    InstallConfig.new(host, conf['hosts']).upload!.install!.reload! if options[:install]
    -    # Clean Wireguard configuration for the host.
    -    WireguardConfig.new(host, conf['hosts']).clean! if options[:clean]
    -  end
    -rescue StandardError => e
    -  puts "Error: #{e.message}"
    -  puts e.backtrace.join("\n")
    -  exit 2
    -end
    +
    begin
    +  options = { hosts: [] }
    +  OptionParser.new do |opts|
    +    opts.banner = 'Usage: wireguardmeshgenerator.rb [options]'
    +    opts.on('--generate', 'Generate Wireguard configs') do
    +      options[:generate] = true
    +    end
    +    opts.on('--install', 'Install Wireguard configs') do
    +      options[:install] = true
    +    end
    +    opts.on('--clean', 'Clean Wireguard configs') do
    +      options[:clean] = true
    +    end
    +    opts.on('--hosts=HOSTS', 'Comma separated hosts to configure') do |hosts|
    +      options[:hosts] = hosts.split(',')
    +    end
    +  end.parse!
    +
    +  conf = YAML.load_file('wireguardmeshgenerator.yaml').freeze
    +  conf['hosts'].keys.select { options[:hosts].empty? || options[:hosts].include?(_1) }
    +               .each do |host|
    +    # Generate Wireguard configuration for the host reload!
    +    WireguardConfig.new(host, conf['hosts']).generate! if options[:generate]
    +    # Install Wireguard configuration for the host.
    +    InstallConfig.new(host, conf['hosts']).upload!.install!.reload! if options[:install]
    +    # Clean Wireguard configuration for the host.
    +    WireguardConfig.new(host, conf['hosts']).clean! if options[:clean]
    +  end
    +rescue StandardError => e
    +  puts "Error: #{e.message}"
    +  puts e.backtrace.join("\n")
    +  exit 2
    +end
     

    And we also have a Rakefile:
    @@ -857,19 +857,19 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    task :generate do
    -  ruby 'wireguardmeshgenerator.rb', '--generate'
    -end
    +
    task :generate do
    +  ruby 'wireguardmeshgenerator.rb', '--generate'
    +end
     
    -task :clean do
    -  ruby 'wireguardmeshgenerator.rb', '--clean'
    -end
    +task :clean do
    +  ruby 'wireguardmeshgenerator.rb', '--clean'
    +end
     
    -task :install do
    -  ruby 'wireguardmeshgenerator.rb', '--install'
    -end
    +task :install do
    +  ruby 'wireguardmeshgenerator.rb', '--install'
    +end
     
    -task default: :generate
    +task default: :generate
     


    @@ -883,16 +883,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    > rake generate
    -/usr/bin/ruby wireguardmeshgenerator.rb --generate
    -Generating dist/f0/etc/wireguard/wg0.conf
    -Generating dist/f1/etc/wireguard/wg0.conf
    -Generating dist/f2/etc/wireguard/wg0.conf
    -Generating dist/r0/etc/wireguard/wg0.conf
    -Generating dist/r1/etc/wireguard/wg0.conf
    -Generating dist/r2/etc/wireguard/wg0.conf
    -Generating dist/blowfish/etc/wireguard/wg0.conf
    -Generating dist/fishfinger/etc/wireguard/wg0.conf
    +
    > rake generate
    +/usr/bin/ruby wireguardmeshgenerator.rb --generate
    +Generating dist/f0/etc/wireguard/wg0.conf
    +Generating dist/f1/etc/wireguard/wg0.conf
    +Generating dist/f2/etc/wireguard/wg0.conf
    +Generating dist/r0/etc/wireguard/wg0.conf
    +Generating dist/r1/etc/wireguard/wg0.conf
    +Generating dist/r2/etc/wireguard/wg0.conf
    +Generating dist/blowfish/etc/wireguard/wg0.conf
    +Generating dist/fishfinger/etc/wireguard/wg0.conf
     

    It generated all the wg0.conf files listed in the output, plus those keys:
    @@ -901,51 +901,51 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    > find keys/ -type f
    -keys/f0/priv.key
    -keys/f0/pub.key
    -keys/psk/f0_f1.key
    -keys/psk/f0_f2.key
    -keys/psk/f0_r0.key
    -keys/psk/f0_r1.key
    -keys/psk/f0_r2.key
    -keys/psk/blowfish_f0.key
    -keys/psk/f0_fishfinger.key
    -keys/psk/f1_f2.key
    -keys/psk/f1_r0.key
    -keys/psk/f1_r1.key
    -keys/psk/f1_r2.key
    -keys/psk/blowfish_f1.key
    -keys/psk/f1_fishfinger.key
    -keys/psk/f2_r0.key
    -keys/psk/f2_r1.key
    -keys/psk/f2_r2.key
    -keys/psk/blowfish_f2.key
    -keys/psk/f2_fishfinger.key
    -keys/psk/r0_r1.key
    -keys/psk/r0_r2.key
    -keys/psk/blowfish_r0.key
    -keys/psk/fishfinger_r0.key
    -keys/psk/r1_r2.key
    -keys/psk/blowfish_r1.key
    -keys/psk/fishfinger_r1.key
    -keys/psk/blowfish_r2.key
    -keys/psk/fishfinger_r2.key
    -keys/psk/blowfish_fishfinger.key
    -keys/f1/priv.key
    -keys/f1/pub.key
    -keys/f2/priv.key
    -keys/f2/pub.key
    -keys/r0/priv.key
    -keys/r0/pub.key
    -keys/r1/priv.key
    -keys/r1/pub.key
    -keys/r2/priv.key
    -keys/r2/pub.key
    -keys/blowfish/priv.key
    -keys/blowfish/pub.key
    -keys/fishfinger/priv.key
    -keys/fishfinger/pub.key
    +
    > find keys/ -type f
    +keys/f0/priv.key
    +keys/f0/pub.key
    +keys/psk/f0_f1.key
    +keys/psk/f0_f2.key
    +keys/psk/f0_r0.key
    +keys/psk/f0_r1.key
    +keys/psk/f0_r2.key
    +keys/psk/blowfish_f0.key
    +keys/psk/f0_fishfinger.key
    +keys/psk/f1_f2.key
    +keys/psk/f1_r0.key
    +keys/psk/f1_r1.key
    +keys/psk/f1_r2.key
    +keys/psk/blowfish_f1.key
    +keys/psk/f1_fishfinger.key
    +keys/psk/f2_r0.key
    +keys/psk/f2_r1.key
    +keys/psk/f2_r2.key
    +keys/psk/blowfish_f2.key
    +keys/psk/f2_fishfinger.key
    +keys/psk/r0_r1.key
    +keys/psk/r0_r2.key
    +keys/psk/blowfish_r0.key
    +keys/psk/fishfinger_r0.key
    +keys/psk/r1_r2.key
    +keys/psk/blowfish_r1.key
    +keys/psk/fishfinger_r1.key
    +keys/psk/blowfish_r2.key
    +keys/psk/fishfinger_r2.key
    +keys/psk/blowfish_fishfinger.key
    +keys/f1/priv.key
    +keys/f1/pub.key
    +keys/f2/priv.key
    +keys/f2/pub.key
    +keys/r0/priv.key
    +keys/r0/pub.key
    +keys/r1/priv.key
    +keys/r1/pub.key
    +keys/r2/priv.key
    +keys/r2/pub.key
    +keys/blowfish/priv.key
    +keys/blowfish/pub.key
    +keys/fishfinger/priv.key
    +keys/fishfinger/pub.key
     

    Those keys are embedded in the resulting wg0.conf, so later, we only need to install the wg0.conf files and not all the keys individually.
    @@ -958,112 +958,112 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    > rake install
    -/usr/bin/ruby wireguardmeshgenerator.rb --install
    -Uploading dist/f0/etc/wireguard/wg0.conf to f0.lan.buetow.org:.
    -Installing Wireguard config on f0
    -Uploading cmd.sh to f0.lan.buetow.org:.
    -+ [ ! -d /usr/local/etc/wireguard ]
    -+ doas chmod 700 /usr/local/etc/wireguard
    -+ doas mv -v wg0.conf /usr/local/etc/wireguard
    -wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    -+ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on f0
    -Uploading cmd.sh to f0.lan.buetow.org:.
    -+ doas service wireguard reload
    -+ rm cmd.sh
    -Uploading dist/f1/etc/wireguard/wg0.conf to f1.lan.buetow.org:.
    -Installing Wireguard config on f1
    -Uploading cmd.sh to f1.lan.buetow.org:.
    -+ [ ! -d /usr/local/etc/wireguard ]
    -+ doas chmod 700 /usr/local/etc/wireguard
    -+ doas mv -v wg0.conf /usr/local/etc/wireguard
    -wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    -+ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on f1
    -Uploading cmd.sh to f1.lan.buetow.org:.
    -+ doas service wireguard reload
    -+ rm cmd.sh
    -Uploading dist/f2/etc/wireguard/wg0.conf to f2.lan.buetow.org:.
    -Installing Wireguard config on f2
    -Uploading cmd.sh to f2.lan.buetow.org:.
    -+ [ ! -d /usr/local/etc/wireguard ]
    -+ doas chmod 700 /usr/local/etc/wireguard
    -+ doas mv -v wg0.conf /usr/local/etc/wireguard
    -wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    -+ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on f2
    -Uploading cmd.sh to f2.lan.buetow.org:.
    -+ doas service wireguard reload
    -+ rm cmd.sh
    -Uploading dist/r0/etc/wireguard/wg0.conf to r0.lan.buetow.org:.
    -Installing Wireguard config on r0
    -Uploading cmd.sh to r0.lan.buetow.org:.
    -+ '[' '!' -d /etc/wireguard ']'
    -+ chmod 700 /etc/wireguard
    -+ mv -v wg0.conf /etc/wireguard
    -renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    -+ chmod 644 /etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on r0
    -Uploading cmd.sh to r0.lan.buetow.org:.
    -+ systemctl reload wg-quick@wg0.service
    -+ rm cmd.sh
    -Uploading dist/r1/etc/wireguard/wg0.conf to r1.lan.buetow.org:.
    -Installing Wireguard config on r1
    -Uploading cmd.sh to r1.lan.buetow.org:.
    -+ '[' '!' -d /etc/wireguard ']'
    -+ chmod 700 /etc/wireguard
    -+ mv -v wg0.conf /etc/wireguard
    -renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    -+ chmod 644 /etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on r1
    -Uploading cmd.sh to r1.lan.buetow.org:.
    -+ systemctl reload wg-quick@wg0.service
    -+ rm cmd.sh
    -Uploading dist/r2/etc/wireguard/wg0.conf to r2.lan.buetow.org:.
    -Installing Wireguard config on r2
    -Uploading cmd.sh to r2.lan.buetow.org:.
    -+ '[' '!' -d /etc/wireguard ']'
    -+ chmod 700 /etc/wireguard
    -+ mv -v wg0.conf /etc/wireguard
    -renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    -+ chmod 644 /etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on r2
    -Uploading cmd.sh to r2.lan.buetow.org:.
    -+ systemctl reload wg-quick@wg0.service
    -+ rm cmd.sh
    -Uploading dist/blowfish/etc/wireguard/wg0.conf to blowfish.buetow.org:.
    -Installing Wireguard config on blowfish
    -Uploading cmd.sh to blowfish.buetow.org:.
    -+ [ ! -d /etc/wireguard ]
    -+ doas chmod 700 /etc/wireguard
    -+ doas mv -v wg0.conf /etc/wireguard
    -wg0.conf -> /etc/wireguard/wg0.conf
    -+ doas chmod 644 /etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on blowfish
    -Uploading cmd.sh to blowfish.buetow.org:.
    -+ doas sh /etc/netstart wg0
    -+ rm cmd.sh
    -Uploading dist/fishfinger/etc/wireguard/wg0.conf to fishfinger.buetow.org:.
    -Installing Wireguard config on fishfinger
    -Uploading cmd.sh to fishfinger.buetow.org:.
    -+ [ ! -d /etc/wireguard ]
    -+ doas chmod 700 /etc/wireguard
    -+ doas mv -v wg0.conf /etc/wireguard
    -wg0.conf -> /etc/wireguard/wg0.conf
    -+ doas chmod 644 /etc/wireguard/wg0.conf
    -+ rm cmd.sh
    -Reloading Wireguard on fishfinger
    -Uploading cmd.sh to fishfinger.buetow.org:.
    -+ doas sh /etc/netstart wg0
    -+ rm cmd.sh
    +
    > rake install
    +/usr/bin/ruby wireguardmeshgenerator.rb --install
    +Uploading dist/f0/etc/wireguard/wg0.conf to f0.lan.buetow.org:.
    +Installing Wireguard config on f0
    +Uploading cmd.sh to f0.lan.buetow.org:.
    ++ [ ! -d /usr/local/etc/wireguard ]
    ++ doas chmod 700 /usr/local/etc/wireguard
    ++ doas mv -v wg0.conf /usr/local/etc/wireguard
    +wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    ++ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on f0
    +Uploading cmd.sh to f0.lan.buetow.org:.
    ++ doas service wireguard reload
    ++ rm cmd.sh
    +Uploading dist/f1/etc/wireguard/wg0.conf to f1.lan.buetow.org:.
    +Installing Wireguard config on f1
    +Uploading cmd.sh to f1.lan.buetow.org:.
    ++ [ ! -d /usr/local/etc/wireguard ]
    ++ doas chmod 700 /usr/local/etc/wireguard
    ++ doas mv -v wg0.conf /usr/local/etc/wireguard
    +wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    ++ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on f1
    +Uploading cmd.sh to f1.lan.buetow.org:.
    ++ doas service wireguard reload
    ++ rm cmd.sh
    +Uploading dist/f2/etc/wireguard/wg0.conf to f2.lan.buetow.org:.
    +Installing Wireguard config on f2
    +Uploading cmd.sh to f2.lan.buetow.org:.
    ++ [ ! -d /usr/local/etc/wireguard ]
    ++ doas chmod 700 /usr/local/etc/wireguard
    ++ doas mv -v wg0.conf /usr/local/etc/wireguard
    +wg0.conf -> /usr/local/etc/wireguard/wg0.conf
    ++ doas chmod 644 /usr/local/etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on f2
    +Uploading cmd.sh to f2.lan.buetow.org:.
    ++ doas service wireguard reload
    ++ rm cmd.sh
    +Uploading dist/r0/etc/wireguard/wg0.conf to r0.lan.buetow.org:.
    +Installing Wireguard config on r0
    +Uploading cmd.sh to r0.lan.buetow.org:.
    ++ '[' '!' -d /etc/wireguard ']'
    ++ chmod 700 /etc/wireguard
    ++ mv -v wg0.conf /etc/wireguard
    +renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    ++ chmod 644 /etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on r0
    +Uploading cmd.sh to r0.lan.buetow.org:.
    ++ systemctl reload wg-quick@wg0.service
    ++ rm cmd.sh
    +Uploading dist/r1/etc/wireguard/wg0.conf to r1.lan.buetow.org:.
    +Installing Wireguard config on r1
    +Uploading cmd.sh to r1.lan.buetow.org:.
    ++ '[' '!' -d /etc/wireguard ']'
    ++ chmod 700 /etc/wireguard
    ++ mv -v wg0.conf /etc/wireguard
    +renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    ++ chmod 644 /etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on r1
    +Uploading cmd.sh to r1.lan.buetow.org:.
    ++ systemctl reload wg-quick@wg0.service
    ++ rm cmd.sh
    +Uploading dist/r2/etc/wireguard/wg0.conf to r2.lan.buetow.org:.
    +Installing Wireguard config on r2
    +Uploading cmd.sh to r2.lan.buetow.org:.
    ++ '[' '!' -d /etc/wireguard ']'
    ++ chmod 700 /etc/wireguard
    ++ mv -v wg0.conf /etc/wireguard
    +renamed 'wg0.conf' -> '/etc/wireguard/wg0.conf'
    ++ chmod 644 /etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on r2
    +Uploading cmd.sh to r2.lan.buetow.org:.
    ++ systemctl reload wg-quick@wg0.service
    ++ rm cmd.sh
    +Uploading dist/blowfish/etc/wireguard/wg0.conf to blowfish.buetow.org:.
    +Installing Wireguard config on blowfish
    +Uploading cmd.sh to blowfish.buetow.org:.
    ++ [ ! -d /etc/wireguard ]
    ++ doas chmod 700 /etc/wireguard
    ++ doas mv -v wg0.conf /etc/wireguard
    +wg0.conf -> /etc/wireguard/wg0.conf
    ++ doas chmod 644 /etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on blowfish
    +Uploading cmd.sh to blowfish.buetow.org:.
    ++ doas sh /etc/netstart wg0
    ++ rm cmd.sh
    +Uploading dist/fishfinger/etc/wireguard/wg0.conf to fishfinger.buetow.org:.
    +Installing Wireguard config on fishfinger
    +Uploading cmd.sh to fishfinger.buetow.org:.
    ++ [ ! -d /etc/wireguard ]
    ++ doas chmod 700 /etc/wireguard
    ++ doas mv -v wg0.conf /etc/wireguard
    +wg0.conf -> /etc/wireguard/wg0.conf
    ++ doas chmod 644 /etc/wireguard/wg0.conf
    ++ rm cmd.sh
    +Reloading Wireguard on fishfinger
    +Uploading cmd.sh to fishfinger.buetow.org:.
    ++ doas sh /etc/netstart wg0
    ++ rm cmd.sh
     

    Re-generating mesh and installing the wg0.conf files again


    @@ -1074,9 +1074,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    > rake clean
    -> rake generate
    -> rake install
    +
    > rake clean
    +> rake generate
    +> rake install
     

    That would also delete and re-generate all the keys involved.
    @@ -1089,52 +1089,52 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas wg show
    -interface: wg0
    -  public key: Jm6YItMt94++dIeOyVi1I9AhNt2qQcryxCZezoX7X2Y=
    -  private key: (hidden)
    -  listening port: 56709
    +
    paul@f0:~ % doas wg show
    +interface: wg0
    +  public key: Jm6YItMt94++dIeOyVi1I9AhNt2qQcryxCZezoX7X2Y=
    +  private key: (hidden)
    +  listening port: 56709
     
    -peer: 8PvGZH1NohHpZPVJyjhctBX9xblsNvYBhpg68FsFcns=
    -  preshared key: (hidden)
    -  endpoint: 46.23.94.99:56709
    -  allowed ips: 192.168.2.111/32
    -  latest handshake: 1 minute, 46 seconds ago
    -  transfer: 124 B received, 1.75 KiB sent
    -  persistent keepalive: every 25 seconds
    +peer: 8PvGZH1NohHpZPVJyjhctBX9xblsNvYBhpg68FsFcns=
    +  preshared key: (hidden)
    +  endpoint: 46.23.94.99:56709
    +  allowed ips: 192.168.2.111/32
    +  latest handshake: 1 minute, 46 seconds ago
    +  transfer: 124 B received, 1.75 KiB sent
    +  persistent keepalive: every 25 seconds
     
    -peer: Xow+d3qVXgUMk4pcRSQ6Fe+vhYBa3VDyHX/4jrGoKns=
    -  preshared key: (hidden)
    -  endpoint: 23.88.35.144:56709
    -  allowed ips: 192.168.2.110/32
    -  latest handshake: 1 minute, 52 seconds ago
    -  transfer: 124 B received, 1.60 KiB sent
    -  persistent keepalive: every 25 seconds
    +peer: Xow+d3qVXgUMk4pcRSQ6Fe+vhYBa3VDyHX/4jrGoKns=
    +  preshared key: (hidden)
    +  endpoint: 23.88.35.144:56709
    +  allowed ips: 192.168.2.110/32
    +  latest handshake: 1 minute, 52 seconds ago
    +  transfer: 124 B received, 1.60 KiB sent
    +  persistent keepalive: every 25 seconds
     
    -peer: s3e93XoY7dPUQgLiVO4d8x/SRCFgEew+/wP7+zwgehI=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.120:56709
    -  allowed ips: 192.168.2.120/32
    +peer: s3e93XoY7dPUQgLiVO4d8x/SRCFgEew+/wP7+zwgehI=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.120:56709
    +  allowed ips: 192.168.2.120/32
     
    -peer: 2htXdNcxzpI2FdPDJy4T4VGtm1wpMEQu1AkQHjNY6F8=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.131:56709
    -  allowed ips: 192.168.2.131/32
    +peer: 2htXdNcxzpI2FdPDJy4T4VGtm1wpMEQu1AkQHjNY6F8=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.131:56709
    +  allowed ips: 192.168.2.131/32
     
    -peer: 0Y/H20W8YIbF7DA1sMwMacLI8WS9yG+1/QO7m2oyllg=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.122:56709
    -  allowed ips: 192.168.2.122/32
    +peer: 0Y/H20W8YIbF7DA1sMwMacLI8WS9yG+1/QO7m2oyllg=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.122:56709
    +  allowed ips: 192.168.2.122/32
     
    -peer: Hhy9kMPOOjChXV2RA5WeCGs+J0FE3rcNPDw/TLSn7i8=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.121:56709
    -  allowed ips: 192.168.2.121/32
    +peer: Hhy9kMPOOjChXV2RA5WeCGs+J0FE3rcNPDw/TLSn7i8=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.121:56709
    +  allowed ips: 192.168.2.121/32
     
    -peer: SlGVsACE1wiaRoGvCR3f7AuHfRS+1jjhS+YwEJ2HvF0=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.132:56709
    -  allowed ips: 192.168.2.132/32
    +peer: SlGVsACE1wiaRoGvCR3f7AuHfRS+1jjhS+YwEJ2HvF0=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.132:56709
    +  allowed ips: 192.168.2.132/32
     

    All the hosts are pingable as well, e.g.:
    @@ -1143,65 +1143,65 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % foreach peer ( f1 f2 r0 r1 r2 blowfish fishfinger )
    -foreach? ping -c2 $peer.wg0
    -foreach? echo
    -foreach? end
    -PING f1.wg0 (192.168.2.131): 56 data bytes
    -64 bytes from 192.168.2.131: icmp_seq=0 ttl=64 time=0.334 ms
    -64 bytes from 192.168.2.131: icmp_seq=1 ttl=64 time=0.260 ms
    +
    paul@f0:~ % foreach peer ( f1 f2 r0 r1 r2 blowfish fishfinger )
    +foreach? ping -c2 $peer.wg0
    +foreach? echo
    +foreach? end
    +PING f1.wg0 (192.168.2.131): 56 data bytes
    +64 bytes from 192.168.2.131: icmp_seq=0 ttl=64 time=0.334 ms
    +64 bytes from 192.168.2.131: icmp_seq=1 ttl=64 time=0.260 ms
     
    ---- f1.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 0.260/0.297/0.334/0.037 ms
    +--- f1.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 0.260/0.297/0.334/0.037 ms
     
    -PING f2.wg0 (192.168.2.132): 56 data bytes
    -64 bytes from 192.168.2.132: icmp_seq=0 ttl=64 time=0.323 ms
    -64 bytes from 192.168.2.132: icmp_seq=1 ttl=64 time=0.303 ms
    +PING f2.wg0 (192.168.2.132): 56 data bytes
    +64 bytes from 192.168.2.132: icmp_seq=0 ttl=64 time=0.323 ms
    +64 bytes from 192.168.2.132: icmp_seq=1 ttl=64 time=0.303 ms
     
    ---- f2.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 0.303/0.313/0.323/0.010 ms
    +--- f2.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 0.303/0.313/0.323/0.010 ms
     
    -PING r0.wg0 (192.168.2.120): 56 data bytes
    -64 bytes from 192.168.2.120: icmp_seq=0 ttl=64 time=0.716 ms
    -64 bytes from 192.168.2.120: icmp_seq=1 ttl=64 time=0.406 ms
    +PING r0.wg0 (192.168.2.120): 56 data bytes
    +64 bytes from 192.168.2.120: icmp_seq=0 ttl=64 time=0.716 ms
    +64 bytes from 192.168.2.120: icmp_seq=1 ttl=64 time=0.406 ms
     
    ---- r0.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 0.406/0.561/0.716/0.155 ms
    +--- r0.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 0.406/0.561/0.716/0.155 ms
     
    -PING r1.wg0 (192.168.2.121): 56 data bytes
    -64 bytes from 192.168.2.121: icmp_seq=0 ttl=64 time=0.639 ms
    -64 bytes from 192.168.2.121: icmp_seq=1 ttl=64 time=0.629 ms
    +PING r1.wg0 (192.168.2.121): 56 data bytes
    +64 bytes from 192.168.2.121: icmp_seq=0 ttl=64 time=0.639 ms
    +64 bytes from 192.168.2.121: icmp_seq=1 ttl=64 time=0.629 ms
     
    ---- r1.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 0.629/0.634/0.639/0.005 ms
    +--- r1.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 0.629/0.634/0.639/0.005 ms
     
    -PING r2.wg0 (192.168.2.122): 56 data bytes
    -64 bytes from 192.168.2.122: icmp_seq=0 ttl=64 time=0.569 ms
    -64 bytes from 192.168.2.122: icmp_seq=1 ttl=64 time=0.479 ms
    +PING r2.wg0 (192.168.2.122): 56 data bytes
    +64 bytes from 192.168.2.122: icmp_seq=0 ttl=64 time=0.569 ms
    +64 bytes from 192.168.2.122: icmp_seq=1 ttl=64 time=0.479 ms
     
    ---- r2.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 0.479/0.524/0.569/0.045 ms
    +--- r2.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 0.479/0.524/0.569/0.045 ms
     
    -PING blowfish.wg0 (192.168.2.110): 56 data bytes
    -64 bytes from 192.168.2.110: icmp_seq=0 ttl=255 time=35.745 ms
    -64 bytes from 192.168.2.110: icmp_seq=1 ttl=255 time=35.481 ms
    +PING blowfish.wg0 (192.168.2.110): 56 data bytes
    +64 bytes from 192.168.2.110: icmp_seq=0 ttl=255 time=35.745 ms
    +64 bytes from 192.168.2.110: icmp_seq=1 ttl=255 time=35.481 ms
     
    ---- blowfish.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 35.481/35.613/35.745/0.132 ms
    +--- blowfish.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 35.481/35.613/35.745/0.132 ms
     
    -PING fishfinger.wg0 (192.168.2.111): 56 data bytes
    -64 bytes from 192.168.2.111: icmp_seq=0 ttl=255 time=33.992 ms
    -64 bytes from 192.168.2.111: icmp_seq=1 ttl=255 time=33.751 ms
    +PING fishfinger.wg0 (192.168.2.111): 56 data bytes
    +64 bytes from 192.168.2.111: icmp_seq=0 ttl=255 time=33.992 ms
    +64 bytes from 192.168.2.111: icmp_seq=1 ttl=255 time=33.751 ms
     
    ---- fishfinger.wg0 ping statistics ---
    -2 packets transmitted, 2 packets received, 0.0% packet loss
    -round-trip min/avg/max/stddev = 33.751/33.872/33.992/0.120 ms
    +--- fishfinger.wg0 ping statistics ---
    +2 packets transmitted, 2 packets received, 0.0% packet loss
    +round-trip min/avg/max/stddev = 33.751/33.872/33.992/0.120 ms
     

    Note that the loop above is a tcsh loop, the default shell used in FreeBSD. Of course, all other peers can ping their peers as well!
    @@ -1212,60 +1212,60 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas wg show
    -interface: wg0
    -  public key: Jm6YItMt94++dIeOyVi1I9AhNt2qQcryxCZezoX7X2Y=
    -  private key: (hidden)
    -  listening port: 56709
    -
    -peer: 0Y/H20W8YIbF7DA1sMwMacLI8WS9yG+1/QO7m2oyllg=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.122:56709
    -  allowed ips: 192.168.2.122/32
    -  latest handshake: 10 seconds ago
    -  transfer: 440 B received, 532 B sent
    -
    -peer: Hhy9kMPOOjChXV2RA5WeCGs+J0FE3rcNPDw/TLSn7i8=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.121:56709
    -  allowed ips: 192.168.2.121/32
    -  latest handshake: 12 seconds ago
    -  transfer: 440 B received, 564 B sent
    -
    -peer: s3e93XoY7dPUQgLiVO4d8x/SRCFgEew+/wP7+zwgehI=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.120:56709
    -  allowed ips: 192.168.2.120/32
    -  latest handshake: 14 seconds ago
    -  transfer: 440 B received, 564 B sent
    -
    -peer: SlGVsACE1wiaRoGvCR3f7AuHfRS+1jjhS+YwEJ2HvF0=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.132:56709
    -  allowed ips: 192.168.2.132/32
    -  latest handshake: 17 seconds ago
    -  transfer: 472 B received, 564 B sent
    -
    -peer: Xow+d3qVXgUMk4pcRSQ6Fe+vhYBa3VDyHX/4jrGoKns=
    -  preshared key: (hidden)
    -  endpoint: 23.88.35.144:56709
    -  allowed ips: 192.168.2.110/32
    -  latest handshake: 55 seconds ago
    -  transfer: 472 B received, 596 B sent
    -  persistent keepalive: every 25 seconds
    -
    -peer: 8PvGZH1NohHpZPVJyjhctBX9xblsNvYBhpg68FsFcns=
    -  preshared key: (hidden)
    -  endpoint: 46.23.94.99:56709
    -  allowed ips: 192.168.2.111/32
    -  latest handshake: 55 seconds ago
    -  transfer: 472 B received, 596 B sent
    -  persistent keepalive: every 25 seconds
    -
    -peer: 2htXdNcxzpI2FdPDJy4T4VGtm1wpMEQu1AkQHjNY6F8=
    -  preshared key: (hidden)
    -  endpoint: 192.168.1.131:56709
    -  allowed ips: 192.168.2.131/32
    +
    paul@f0:~ % doas wg show
    +interface: wg0
    +  public key: Jm6YItMt94++dIeOyVi1I9AhNt2qQcryxCZezoX7X2Y=
    +  private key: (hidden)
    +  listening port: 56709
    +
    +peer: 0Y/H20W8YIbF7DA1sMwMacLI8WS9yG+1/QO7m2oyllg=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.122:56709
    +  allowed ips: 192.168.2.122/32
    +  latest handshake: 10 seconds ago
    +  transfer: 440 B received, 532 B sent
    +
    +peer: Hhy9kMPOOjChXV2RA5WeCGs+J0FE3rcNPDw/TLSn7i8=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.121:56709
    +  allowed ips: 192.168.2.121/32
    +  latest handshake: 12 seconds ago
    +  transfer: 440 B received, 564 B sent
    +
    +peer: s3e93XoY7dPUQgLiVO4d8x/SRCFgEew+/wP7+zwgehI=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.120:56709
    +  allowed ips: 192.168.2.120/32
    +  latest handshake: 14 seconds ago
    +  transfer: 440 B received, 564 B sent
    +
    +peer: SlGVsACE1wiaRoGvCR3f7AuHfRS+1jjhS+YwEJ2HvF0=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.132:56709
    +  allowed ips: 192.168.2.132/32
    +  latest handshake: 17 seconds ago
    +  transfer: 472 B received, 564 B sent
    +
    +peer: Xow+d3qVXgUMk4pcRSQ6Fe+vhYBa3VDyHX/4jrGoKns=
    +  preshared key: (hidden)
    +  endpoint: 23.88.35.144:56709
    +  allowed ips: 192.168.2.110/32
    +  latest handshake: 55 seconds ago
    +  transfer: 472 B received, 596 B sent
    +  persistent keepalive: every 25 seconds
    +
    +peer: 8PvGZH1NohHpZPVJyjhctBX9xblsNvYBhpg68FsFcns=
    +  preshared key: (hidden)
    +  endpoint: 46.23.94.99:56709
    +  allowed ips: 192.168.2.111/32
    +  latest handshake: 55 seconds ago
    +  transfer: 472 B received, 596 B sent
    +  persistent keepalive: every 25 seconds
    +
    +peer: 2htXdNcxzpI2FdPDJy4T4VGtm1wpMEQu1AkQHjNY6F8=
    +  preshared key: (hidden)
    +  endpoint: 192.168.1.131:56709
    +  allowed ips: 192.168.2.131/32
     

    Conclusion


    @@ -1486,14 +1486,14 @@ set-option -g prefix C-g by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    function tmux::search
    -    set -l session (tmux list-sessions | fzf | cut -d: -f1)
    -    if test -z "$TMUX"
    -        tmux attach-session -t $session
    -    else
    -        tmux switch -t $session
    -    end
    -end
    +
    function tmux::search
    +    set -l session (tmux list-sessions | fzf | cut -d: -f1)
    +    if test -z "$TMUX"
    +        tmux attach-session -t $session
    +    else
    +        tmux switch -t $session
    +    end
    +end
     

    All it does is list all currently open sessions in fzf, where one of them can be searched and selected through fuzzy find, and then either switch (if already inside a session) to the other session or attach to the other session (if not yet in Tmux).
    @@ -1906,10 +1906,10 @@ __ejm\___/________dwb`---`______________________ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % dmesg | grep 'Features2=.*POPCNT'
    -  Features2=0x7ffafbbf<SSE3,PCLMULQDQ,DTES64,MON,DS_CPL,VMX,EST,TM2,SSSE3,SDBG,
    -	FMA,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,TSCDLT,AESNI,XSAVE,
    -	OSXSAVE,AVX,F16C,RDRAND>
    +
    paul@f0:~ % dmesg | grep 'Features2=.*POPCNT'
    +  Features2=0x7ffafbbf<SSE3,PCLMULQDQ,DTES64,MON,DS_CPL,VMX,EST,TM2,SSSE3,SDBG,
    +	FMA,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,TSCDLT,AESNI,XSAVE,
    +	OSXSAVE,AVX,F16C,RDRAND>
     

    So it's there! All good.
    @@ -1926,15 +1926,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas pkg install vm-bhyve bhyve-firmware
    -paul@f0:~ % doas sysrc vm_enable=YES
    -vm_enable:  -> YES
    -paul@f0:~ % doas sysrc vm_dir=zfs:zroot/bhyve
    -vm_dir:  -> zfs:zroot/bhyve
    -paul@f0:~ % doas zfs create zroot/bhyve
    -paul@f0:~ % doas vm init
    -paul@f0:~ % doas vm switch create public
    -paul@f0:~ % doas vm switch add public re0
    +
    paul@f0:~ % doas pkg install vm-bhyve bhyve-firmware
    +paul@f0:~ % doas sysrc vm_enable=YES
    +vm_enable:  -> YES
    +paul@f0:~ % doas sysrc vm_dir=zfs:zroot/bhyve
    +vm_dir:  -> zfs:zroot/bhyve
    +paul@f0:~ % doas zfs create zroot/bhyve
    +paul@f0:~ % doas vm init
    +paul@f0:~ % doas vm switch create public
    +paul@f0:~ % doas vm switch add public re0
     

    Bhyve stores all it's data in the /bhyve of the zroot ZFS pool:
    @@ -1943,8 +1943,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % zfs list | grep bhyve
    -zroot/bhyve                                   1.74M   453G  1.74M  /zroot/bhyve
    +
    paul@f0:~ % zfs list | grep bhyve
    +zroot/bhyve                                   1.74M   453G  1.74M  /zroot/bhyve
     

    For convenience, we also create this symlink:
    @@ -1953,7 +1953,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas ln -s /zroot/bhyve/ /bhyve
    +
    paul@f0:~ % doas ln -s /zroot/bhyve/ /bhyve
     
     

    @@ -1963,8 +1963,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas vm list
    -NAME  DATASTORE  LOADER  CPU  MEMORY  VNC  AUTO  STATE
    +
    paul@f0:~ % doas vm list
    +NAME  DATASTORE  LOADER  CPU  MEMORY  VNC  AUTO  STATE
     

    Rocky Linux VMs


    @@ -1985,10 +1985,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas vm iso \
    - https://download.rockylinux.org/pub/rocky/9/isos/x86_64/Rocky-9.5-x86_64-minimal.iso
    -/zroot/bhyve/.iso/Rocky-9.5-x86_64-minimal.iso        1808 MB 4780 kBps 06m28s
    -paul@f0:/bhyve % doas vm create rocky
    +
    paul@f0:~ % doas vm iso \
    + https://download.rockylinux.org/pub/rocky/9/isos/x86_64/Rocky-9.5-x86_64-minimal.iso
    +/zroot/bhyve/.iso/Rocky-9.5-x86_64-minimal.iso        1808 MB 4780 kBps 06m28s
    +paul@f0:/bhyve % doas vm create rocky
     

    VM configuration


    @@ -1999,16 +1999,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/bhyve/rocky % cat rocky.conf
    -loader="bhyveload"
    -cpu=1
    -memory=256M
    -network0_type="virtio-net"
    -network0_switch="public"
    -disk0_type="virtio-blk"
    -disk0_name="disk0.img"
    -uuid="1c4655ac-c828-11ef-a920-e8ff1ed71ca0"
    -network0_mac="58:9c:fc:0d:13:3f"
    +
    paul@f0:/bhyve/rocky % cat rocky.conf
    +loader="bhyveload"
    +cpu=1
    +memory=256M
    +network0_type="virtio-net"
    +network0_switch="public"
    +disk0_type="virtio-blk"
    +disk0_name="disk0.img"
    +uuid="1c4655ac-c828-11ef-a920-e8ff1ed71ca0"
    +network0_mac="58:9c:fc:0d:13:3f"
     

    The uuid and the network0_mac differ for each of the three VMs (the ones being installed on f0, f1 and f2).
    @@ -2039,17 +2039,17 @@ network0_mac="58:9c:fc:0d:13:3f" by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas vm install rocky Rocky-9.5-x86_64-minimal.iso
    -Starting rocky
    -  * found guest in /zroot/bhyve/rocky
    -  * booting...
    +
    paul@f0:~ % doas vm install rocky Rocky-9.5-x86_64-minimal.iso
    +Starting rocky
    +  * found guest in /zroot/bhyve/rocky
    +  * booting...
     
    -paul@f0:/bhyve/rocky % doas vm list
    -NAME   DATASTORE  LOADER  CPU  MEMORY  VNC           AUTO  STATE
    -rocky  default    uefi    4    14G     0.0.0.0:5900  No    Locked (f0.lan.buetow.org)
    +paul@f0:/bhyve/rocky % doas vm list
    +NAME   DATASTORE  LOADER  CPU  MEMORY  VNC           AUTO  STATE
    +rocky  default    uefi    4    14G     0.0.0.0:5900  No    Locked (f0.lan.buetow.org)
     
    -paul@f0:/bhyve/rocky % doas sockstat -4 | grep 5900
    -root     bhyve       6079 8   tcp4   *:5900                *:*
    +paul@f0:/bhyve/rocky % doas sockstat -4 | grep 5900
    +root     bhyve       6079 8   tcp4   *:5900                *:*
     

    Port 5900 now also opens for VNC connections, so I connected it with a VNC client and ran through the installation dialogues. This could be done unattended or more automated, but there are only three VMs to install, and the automation doesn't seem worth it as we do it only once a year or less often.
    @@ -2062,9 +2062,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/bhyve/rocky % doas vm stop rocky
    -paul@f0:/bhyve/rocky % doas truncate -s 100G disk0.img
    -paul@f0:/bhyve/rocky % doas vm install rocky Rocky-9.5-x86_64-minimal.iso
    +
    paul@f0:/bhyve/rocky % doas vm stop rocky
    +paul@f0:/bhyve/rocky % doas truncate -s 100G disk0.img
    +paul@f0:/bhyve/rocky % doas vm install rocky Rocky-9.5-x86_64-minimal.iso
     

    Connect to VNC


    @@ -2093,9 +2093,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/bhyve/rocky % cat <<END | doas tee -a /etc/rc.conf
    -vm_list="rocky"
    -vm_delay="5"
    +
    paul@f0:/bhyve/rocky % cat <<END | doas tee -a /etc/rc.conf
    +vm_list="rocky"
    +vm_delay="5"
     

    The vm_delay isn't really required. It is used to wait 5 seconds before starting each VM, but there is currently only one VM per host. Maybe later, when there are more, this will be useful. After adding, there's now a Yes indicator in the AUTO column.
    @@ -2104,9 +2104,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas vm list
    -NAME   DATASTORE  LOADER  CPU  MEMORY  VNC           AUTO     STATE
    -rocky  default    uefi    4    14G     0.0.0.0:5900  Yes [1]  Running (2063)
    +
    paul@f0:~ % doas vm list
    +NAME   DATASTORE  LOADER  CPU  MEMORY  VNC           AUTO     STATE
    +rocky  default    uefi    4    14G     0.0.0.0:5900  Yes [1]  Running (2063)
     

    Static IP configuration


    @@ -2125,11 +2125,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/bhyve/rocky % cat <<END | doas tee -a /etc/hosts
    -192.168.1.120 r0 r0.lan r0.lan.buetow.org
    -192.168.1.121 r1 r1.lan r1.lan.buetow.org
    -192.168.1.122 r2 r2.lan r2.lan.buetow.org
    -END
    +
    paul@f0:/bhyve/rocky % cat <<END | doas tee -a /etc/hosts
    +192.168.1.120 r0 r0.lan r0.lan.buetow.org
    +192.168.1.121 r1 r1.lan r1.lan.buetow.org
    +192.168.1.122 r2 r2.lan r2.lan.buetow.org
    +END
     

    And we configure the IPs accordingly on the VMs themselves by opening a root shell via SSH to the VMs and entering the following commands on each of the VMs:
    @@ -2138,18 +2138,18 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] % dnmcli connection modify enp0s5 ipv4.address 192.168.1.120/24
    -[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.gateway 192.168.1.1
    -[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.DNS 192.168.1.1
    -[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.method manual
    -[root@r0 ~] % dnmcli connection down enp0s5
    -[root@r0 ~] % dnmcli connection up enp0s5
    -[root@r0 ~] % hostnamectl set-hostname r0.lan.buetow.org
    -[root@r0 ~] % cat <<END >>/etc/hosts
    -192.168.1.120 r0 r0.lan r0.lan.buetow.org
    -192.168.1.121 r1 r1.lan r1.lan.buetow.org
    -192.168.1.122 r2 r2.lan r2.lan.buetow.org
    -END
    +
    [root@r0 ~] % dnmcli connection modify enp0s5 ipv4.address 192.168.1.120/24
    +[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.gateway 192.168.1.1
    +[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.DNS 192.168.1.1
    +[root@r0 ~] % dnmcli connection modify enp0s5 ipv4.method manual
    +[root@r0 ~] % dnmcli connection down enp0s5
    +[root@r0 ~] % dnmcli connection up enp0s5
    +[root@r0 ~] % hostnamectl set-hostname r0.lan.buetow.org
    +[root@r0 ~] % cat <<END >>/etc/hosts
    +192.168.1.120 r0 r0.lan r0.lan.buetow.org
    +192.168.1.121 r1 r1.lan r1.lan.buetow.org
    +192.168.1.122 r2 r2.lan r2.lan.buetow.org
    +END
     

    Whereas:
    @@ -2170,7 +2170,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % for i in 0 1 2; do ssh-copy-id root@r$i.lan.buetow.org; done
    +
    % for i in 0 1 2; do ssh-copy-id root@r$i.lan.buetow.org; done
     

    Then, we edit the /etc/ssh/sshd_config file again on all three VMs and configure PasswordAuthentication no to only allow SSH key authentication from now on.
    @@ -2181,8 +2181,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~] % dnf update
    -[root@r0 ~] % reboot
    +
    [root@r0 ~] % dnf update
    +[root@r0 ~] % reboot
     

    Stress testing CPU


    @@ -2193,28 +2193,28 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    package main
    +
    package main
     
    -import "testing"
    +import "testing"
     
    -func BenchmarkCPUSilly1(b *testing.B) {
    -	for i := 0; i < b.N; i++ {
    -		_ = i * i
    -	}
    -}
    +func BenchmarkCPUSilly1(b *testing.B) {
    +	for i := 0; i < b.N; i++ {
    +		_ = i * i
    +	}
    +}
     
    -func BenchmarkCPUSilly2(b *testing.B) {
    -	var sillyResult float64
    -	for i := 0; i < b.N; i++ {
    -		sillyResult += float64(i)
    -		sillyResult *= float64(i)
    -		divisor := float64(i) + 1
    -		if divisor > 0 {
    -			sillyResult /= divisor
    -		}
    -	}
    -	_ = sillyResult // to avoid compiler optimization
    -}
    +func BenchmarkCPUSilly2(b *testing.B) {
    +	var sillyResult float64
    +	for i := 0; i < b.N; i++ {
    +		sillyResult += float64(i)
    +		sillyResult *= float64(i)
    +		divisor := float64(i) + 1
    +		if divisor > 0 {
    +			sillyResult /= divisor
    +		}
    +	}
    +	_ = sillyResult // to avoid compiler optimization
    +}
     

    You can find the repository here:
    @@ -2229,10 +2229,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas pkg install git go
    -paul@f0:~ % mkdir ~/git && cd ~/git && \
    -  git clone https://codeberg.org/snonux/sillybench && \
    -  cd sillybench
    +
    paul@f0:~ % doas pkg install git go
    +paul@f0:~ % mkdir ~/git && cd ~/git && \
    +  git clone https://codeberg.org/snonux/sillybench && \
    +  cd sillybench
     

    And to run it:
    @@ -2241,18 +2241,18 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~/git/sillybench % go version
    -go version go1.24.1 freebsd/amd64
    +
    paul@f0:~/git/sillybench % go version
    +go version go1.24.1 freebsd/amd64
     
    -paul@f0:~/git/sillybench % go test -bench=.
    -goos: freebsd
    -goarch: amd64
    -pkg: codeberg.org/snonux/sillybench
    -cpu: Intel(R) N100
    -BenchmarkCPUSilly1-4    1000000000               0.4022 ns/op
    -BenchmarkCPUSilly2-4    1000000000               0.4027 ns/op
    -PASS
    -ok      codeberg.org/snonux/sillybench 0.891s
    +paul@f0:~/git/sillybench % go test -bench=.
    +goos: freebsd
    +goarch: amd64
    +pkg: codeberg.org/snonux/sillybench
    +cpu: Intel(R) N100
    +BenchmarkCPUSilly1-4    1000000000               0.4022 ns/op
    +BenchmarkCPUSilly2-4    1000000000               0.4027 ns/op
    +PASS
    +ok      codeberg.org/snonux/sillybench 0.891s
     

    Silly Rocky Linux VM @ Bhyve benchmark


    @@ -2263,10 +2263,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 ~]# dnf install golang git
    -[root@r0 ~]# mkdir ~/git && cd ~/git && \
    -  git clone https://codeberg.org/snonux/sillybench && \
    -  cd sillybench
    +
    [root@r0 ~]# dnf install golang git
    +[root@r0 ~]# mkdir ~/git && cd ~/git && \
    +  git clone https://codeberg.org/snonux/sillybench && \
    +  cd sillybench
     

    And to run it:
    @@ -2275,15 +2275,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [root@r0 sillybench]# go version
    -go version go1.22.9 (Red Hat 1.22.9-2.el9_5) linux/amd64
    -[root@r0 sillybench]# go test -bench=.
    -goos: linux
    -goarch: amd64
    -pkg: codeberg.org/snonux/sillybench
    -cpu: Intel(R) N100
    -BenchmarkCPUSilly1-4    1000000000               0.4347 ns/op
    -BenchmarkCPUSilly2-4    1000000000               0.4345 ns/op
    +
    [root@r0 sillybench]# go version
    +go version go1.22.9 (Red Hat 1.22.9-2.el9_5) linux/amd64
    +[root@r0 sillybench]# go test -bench=.
    +goos: linux
    +goarch: amd64
    +pkg: codeberg.org/snonux/sillybench
    +cpu: Intel(R) N100
    +BenchmarkCPUSilly1-4    1000000000               0.4347 ns/op
    +BenchmarkCPUSilly2-4    1000000000               0.4345 ns/op
     

    The Linux benchmark is slightly slower than the FreeBSD one. The Go version is also a bit older. I tried the same with the up-to-date version of Go (1.24.x) with similar results. There could be a slight Bhyve overhead, or FreeBSD is just slightly more efficient in this benchmark. Overall, this shows that Bhyve performs excellently.
    @@ -2298,15 +2298,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@freebsd:~/git/sillybench # go test -bench=.
    -goos: freebsd
    -goarch: amd64
    -pkg: codeberg.org/snonux/sillybench
    -cpu: Intel(R) N100
    -BenchmarkCPUSilly1      1000000000               0.4273 ns/op
    -BenchmarkCPUSilly2      1000000000               0.4286 ns/op
    -PASS
    -ok      codeberg.org/snonux/sillybench  0.949s
    +
    root@freebsd:~/git/sillybench # go test -bench=.
    +goos: freebsd
    +goarch: amd64
    +pkg: codeberg.org/snonux/sillybench
    +cpu: Intel(R) N100
    +BenchmarkCPUSilly1      1000000000               0.4273 ns/op
    +BenchmarkCPUSilly2      1000000000               0.4286 ns/op
    +PASS
    +ok      codeberg.org/snonux/sillybench  0.949s
     

    It's a bit better than Linux! I am sure that this is not really a scientific benchmark, so take the results with a grain of salt!
    @@ -2323,16 +2323,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas ubench -s 1
    -Unix Benchmark Utility v.0.3
    -Copyright (C) July, 1999 PhysTech, Inc.
    -Author: Sergei Viznyuk <sv@phystech.com>
    -http://www.phystech.com/download/ubench.html
    -FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    -Ubench Single CPU:   671010 (0.40s)
    -Ubench Single MEM:  1705237 (0.48s)
    ------------------------------------
    -Ubench Single AVG:  1188123
    +
    paul@f0:~ % doas ubench -s 1
    +Unix Benchmark Utility v.0.3
    +Copyright (C) July, 1999 PhysTech, Inc.
    +Author: Sergei Viznyuk <sv@phystech.com>
    +http://www.phystech.com/download/ubench.html
    +FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    +Ubench Single CPU:   671010 (0.40s)
    +Ubench Single MEM:  1705237 (0.48s)
    +-----------------------------------
    +Ubench Single AVG:  1188123
     
     

    @@ -2342,16 +2342,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas ubench
    -Unix Benchmark Utility v.0.3
    -Copyright (C) July, 1999 PhysTech, Inc.
    -Author: Sergei Viznyuk <sv@phystech.com>
    -http://www.phystech.com/download/ubench.html
    -FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    -Ubench CPU:  2660220
    -Ubench MEM:  3095182
    ---------------------
    -Ubench AVG:  2877701
    +
    paul@f0:~ % doas ubench
    +Unix Benchmark Utility v.0.3
    +Copyright (C) July, 1999 PhysTech, Inc.
    +Author: Sergei Viznyuk <sv@phystech.com>
    +http://www.phystech.com/download/ubench.html
    +FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    +Ubench CPU:  2660220
    +Ubench MEM:  3095182
    +--------------------
    +Ubench AVG:  2877701
     

    FreeBSD VM @ Bhyve ubench benchmark


    @@ -2362,16 +2362,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@freebsd:~ # ubench -s 1
    -Unix Benchmark Utility v.0.3
    -Copyright (C) July, 1999 PhysTech, Inc.
    -Author: Sergei Viznyuk <sv@phystech.com>
    -http://www.phystech.com/download/ubench.html
    -FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    -Ubench Single CPU:   672792 (0.40s)
    -Ubench Single MEM:   852757 (0.48s)
    ------------------------------------
    -Ubench Single AVG:   762774
    +
    root@freebsd:~ # ubench -s 1
    +Unix Benchmark Utility v.0.3
    +Copyright (C) July, 1999 PhysTech, Inc.
    +Author: Sergei Viznyuk <sv@phystech.com>
    +http://www.phystech.com/download/ubench.html
    +FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    +Ubench Single CPU:   672792 (0.40s)
    +Ubench Single MEM:   852757 (0.48s)
    +-----------------------------------
    +Ubench Single AVG:   762774
     

    Wow, the CPU in the VM was a tiny bit faster than on the host! So this was probably just a glitch in the matrix. Memory seems slower, though.
    @@ -2382,24 +2382,24 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@freebsd:~ # ubench
    -Unix Benchmark Utility v.0.3
    -Copyright (C) July, 1999 PhysTech, Inc.
    -Author: Sergei Viznyuk <sv@phystech.com>
    -http://www.phystech.com/download/ubench.html
    -FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    -Ubench CPU:  2652857
    -swap_pager: out of swap space
    -swp_pager_getswapspace(27): failed
    -swap_pager: out of swap space
    -swp_pager_getswapspace(18): failed
    -Apr  4 23:02:43 freebsd kernel: pid 862 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    -swp_pager_getswapspace(6): failed
    -Apr  4 23:02:46 freebsd kernel: pid 863 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    -Apr  4 23:02:47 freebsd kernel: pid 864 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    -Apr  4 23:02:48 freebsd kernel: pid 865 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    -Apr  4 23:02:49 freebsd kernel: pid 861 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    -Apr  4 23:02:51 freebsd kernel: pid 839 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +
    root@freebsd:~ # ubench
    +Unix Benchmark Utility v.0.3
    +Copyright (C) July, 1999 PhysTech, Inc.
    +Author: Sergei Viznyuk <sv@phystech.com>
    +http://www.phystech.com/download/ubench.html
    +FreeBSD 14.2-RELEASE-p1 FreeBSD 14.2-RELEASE-p1 GENERIC amd64
    +Ubench CPU:  2652857
    +swap_pager: out of swap space
    +swp_pager_getswapspace(27): failed
    +swap_pager: out of swap space
    +swp_pager_getswapspace(18): failed
    +Apr  4 23:02:43 freebsd kernel: pid 862 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +swp_pager_getswapspace(6): failed
    +Apr  4 23:02:46 freebsd kernel: pid 863 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +Apr  4 23:02:47 freebsd kernel: pid 864 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +Apr  4 23:02:48 freebsd kernel: pid 865 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +Apr  4 23:02:49 freebsd kernel: pid 861 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
    +Apr  4 23:02:51 freebsd kernel: pid 839 (ubench), jid 0, uid 0, was killed: failed to reclaim memory
     

    The multi-CPU benchmark in the Bhyve VM ran with almost identical results to the FreeBSD host system. However, the memory benchmark failed with out-of-swap space errors. I am unsure why, as the VM has 14GB RAM, but I am not investigating further.
    @@ -2533,8 +2533,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    git clone https://codeberg.org/snonux/gos.git
    -cd gos
    +
    git clone https://codeberg.org/snonux/gos.git
    +cd gos
     

    Build the binaries:
    @@ -2543,10 +2543,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    go build -o gos ./cmd/gos
    -go build -o gosc ./cmd/gosc
    -sudo mv gos ~/go/bin
    -sudo mv gosc ~/go/bin
    +
    go build -o gos ./cmd/gos
    +go build -o gosc ./cmd/gosc
    +sudo mv gos ~/go/bin
    +sudo mv gosc ~/go/bin
     

    Or, if you want to use the Taskfile:
    @@ -2555,7 +2555,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    go-task install
    +
    go-task install
     

    Configuration


    @@ -2568,13 +2568,13 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    {
    -  "MastodonURL": "https://mastodon.example.com",
    -  "MastodonAccessToken": "your-mastodon-access-token",
    -  "LinkedInClientID": "your-linkedin-client-id",
    -  "LinkedInSecret": "your-linkedin-client-secret",
    -  "LinkedInRedirectURL": "http://localhost:8080/callback",
    -}
    +
    {
    +  "MastodonURL": "https://mastodon.example.com",
    +  "MastodonAccessToken": "your-mastodon-access-token",
    +  "LinkedInClientID": "your-linkedin-client-id",
    +  "LinkedInSecret": "your-linkedin-client-secret",
    +  "LinkedInRedirectURL": "http://localhost:8080/callback",
    +}
     

    Configuration fields


    @@ -2630,7 +2630,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ./gos --dry
    +
    ./gos --dry
     

    *Normal run*
    @@ -2641,7 +2641,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ./gos 
    +
    ./gos 
     

    :-)
    @@ -2806,7 +2806,7 @@ Hello World :-) by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    gos --geminiSummaryFor 202410,202411,202412
    +
    gos --geminiSummaryFor 202410,202411,202412
     

    This outputs the summary for the three specified months, as shown in the example. The summary includes posts from all social media networks but removes duplicates.
    @@ -2818,7 +2818,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    gos --gemtexterEnable --geminiSummaryFor 202410,202411,202412
    +
    gos --gemtexterEnable --geminiSummaryFor 202410,202411,202412
     

    Gemtexter
    @@ -2829,7 +2829,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    gos --gemtexterEnable --geminiSummaryFor 202410,202411,202412 --geminiCapsules "foo.zone,paul.buetow.org"
    +
    gos --gemtexterEnable --geminiSummaryFor 202410,202411,202412 --geminiCapsules "foo.zone,paul.buetow.org"
     

    It will then also generate Gemini Gemtext links in the summary page and flag them with (Gemini).
    @@ -2924,25 +2924,25 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    package main
    +
    package main
     
    -import "log"
    +import "log"
     
    -type fun func() string
    +type fun func() string
     
    -func (f fun) Bar() string {
    -        return "Bar"
    -}
    +func (f fun) Bar() string {
    +        return "Bar"
    +}
     
    -func main() {
    -        var f fun = func() string {
    -                return "Foo"
    -        }
    -        log.Println("Example 1: ", f())
    -        log.Println("Example 2: ", f.Bar())
    -        log.Println("Example 3: ", fun(f.Bar).Bar())
    -        log.Println("Example 4: ", fun(fun(f.Bar).Bar).Bar())
    -}
    +func main() {
    +        var f fun = func() string {
    +                return "Foo"
    +        }
    +        log.Println("Example 1: ", f())
    +        log.Println("Example 2: ", f.Bar())
    +        log.Println("Example 3: ", fun(f.Bar).Bar())
    +        log.Println("Example 4: ", fun(fun(f.Bar).Bar).Bar())
    +}
     

    It runs just fine:
    @@ -2951,11 +2951,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ❯ go run main.go
    -2025/02/07 22:56:14 Example 1:  Foo
    -2025/02/07 22:56:14 Example 2:  Bar
    -2025/02/07 22:56:14 Example 3:  Bar
    -2025/02/07 22:56:14 Example 4:  Bar
    +
    ❯ go run main.go
    +2025/02/07 22:56:14 Example 1:  Foo
    +2025/02/07 22:56:14 Example 2:  Bar
    +2025/02/07 22:56:14 Example 3:  Bar
    +2025/02/07 22:56:14 Example 4:  Bar
     

    macOS


    @@ -2974,20 +2974,20 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ❯ touch Maß
    -❯ ls -l
    --rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Maß
    -❯ touch Mass
    -❯ ls -l
    --rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Maß
    -❯ rm Mass
    -❯ ls -l
    +
    ❯ touch Maß
    +❯ ls -l
    +-rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Maß
    +❯ touch Mass
    +❯ ls -l
    +-rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Maß
    +❯ rm Mass
    +❯ ls -l
     
    -❯ touch Mass
    -❯ ls -ltr
    --rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Mass
    -❯ rm Maß
    -❯ ls -l
    +❯ touch Mass
    +❯ ls -ltr
    +-rw-r--r--@ 1 paul  wheel  0 Feb  7 23:02 Mass
    +❯ rm Maß
    +❯ ls -l
     
     

    @@ -3031,16 +3031,16 @@ ADFS::4.$.Documents.Techwriter.Myfile by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    arr = {10, 20, 30, 40, 50}
    -print(arr[1]) -- Accessing the first element
    +
    arr = {10, 20, 30, 40, 50}
    +print(arr[1]) -- Accessing the first element
     

    -
    ❯ lua foo.lua
    -10
    +
    ❯ lua foo.lua
    +10
     

    One-based indexing is more natural for human-readable, mathematical, and theoretical contexts, where counting traditionally starts from one.
    @@ -3055,45 +3055,45 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    # (C) 2006 by Paul C. Buetow
    +
    # (C) 2006 by Paul C. Buetow
     
    -Christmas:{time;#!!!
    +Christmas:{time;#!!!
     
    -Children: do tell $wishes;
    +Children: do tell $wishes;
     
    -Santa: for $each (@children) { 
    -BEGIN { read $each, $their, wishes and study them; use Memoize#ing
    +Santa: for $each (@children) { 
    +BEGIN { read $each, $their, wishes and study them; use Memoize#ing
     
    -} use constant gift, 'wrapping'; 
    -package Gifts; pack $each, gift and bless $each and goto deliver
    -or do import if not local $available,!!! HO, HO, HO;
    +} use constant gift, 'wrapping'; 
    +package Gifts; pack $each, gift and bless $each and goto deliver
    +or do import if not local $available,!!! HO, HO, HO;
     
    -redo Santa, pipe $gifts, to_childs;
    -redo Santa and do return if last one, is, delivered; 
    +redo Santa, pipe $gifts, to_childs;
    +redo Santa and do return if last one, is, delivered; 
     
    -deliver: gift and require diagnostics if our $gifts ,not break;
    -do{ use NEXT; time; tied $gifts} if broken and dump the, broken, ones;
    -The_children: sleep and wait for (each %gift) and try { to => untie $gifts };
    +deliver: gift and require diagnostics if our $gifts ,not break;
    +do{ use NEXT; time; tied $gifts} if broken and dump the, broken, ones;
    +The_children: sleep and wait for (each %gift) and try { to => untie $gifts };
     
    -redo Santa, pipe $gifts, to_childs;
    -redo Santa and do return if last one, is, delivered; 
    +redo Santa, pipe $gifts, to_childs;
    +redo Santa and do return if last one, is, delivered; 
     
    -The_christmas_tree: formline s/ /childrens/, $gifts;
    -alarm and warn if not exists $Christmas{ tree}, @t, $ENV{HOME};  
    -write <<EMail
    - to the parents to buy a new christmas tree!!!!111
    - and send the
    -EMail
    -;wait and redo deliver until defined local $tree;
    +The_christmas_tree: formline s/ /childrens/, $gifts;
    +alarm and warn if not exists $Christmas{ tree}, @t, $ENV{HOME};  
    +write <<EMail
    + to the parents to buy a new christmas tree!!!!111
    + and send the
    +EMail
    +;wait and redo deliver until defined local $tree;
     
    -redo Santa, pipe $gifts, to_childs;
    -redo Santa and do return if last one, is, delivered ;}
    +redo Santa, pipe $gifts, to_childs;
    +redo Santa and do return if last one, is, delivered ;}
     
    -END {} our $mission and do sleep until next Christmas ;}
    +END {} our $mission and do sleep until next Christmas ;}
     
    -__END__
    +__END__
     
    -This is perl, v5.8.8 built for i386-freebsd-64int
    +This is perl, v5.8.8 built for i386-freebsd-64int
     

    More Perl Poetry of mine
    @@ -3190,11 +3190,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0: ~ % doas freebsd-update fetch
    -paul@f0: ~ % doas freebsd-update install
    -paul@f0: ~ % doas freebsd-update -r 14.2-RELEASE upgrade
    -paul@f0: ~ % doas freebsd-update install
    -paul@f0: ~ % doas shutdown -r now
    +
    paul@f0: ~ % doas freebsd-update fetch
    +paul@f0: ~ % doas freebsd-update install
    +paul@f0: ~ % doas freebsd-update -r 14.2-RELEASE upgrade
    +paul@f0: ~ % doas freebsd-update install
    +paul@f0: ~ % doas shutdown -r now
     

    And after rebooting, I ran:
    @@ -3203,10 +3203,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0: ~ % doas freebsd-update install
    -paul@f0: ~ % doas pkg update
    -paul@f0: ~ % doas pkg upgrade
    -paul@f0: ~ % doas shutdown -r now
    +
    paul@f0: ~ % doas freebsd-update install
    +paul@f0: ~ % doas pkg update
    +paul@f0: ~ % doas pkg upgrade
    +paul@f0: ~ % doas shutdown -r now
     

    And after another reboot, I was on 14.2:
    @@ -3215,9 +3215,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % uname -a
    -FreeBSD f0.lan.buetow.org 14.2-RELEASE FreeBSD 14.2-RELEASE 
    - releng/14.2-n269506-c8918d6c7412 GENERIC amd64
    +
    paul@f0:~ % uname -a
    +FreeBSD f0.lan.buetow.org 14.2-RELEASE FreeBSD 14.2-RELEASE 
    + releng/14.2-n269506-c8918d6c7412 GENERIC amd64
     

    And, of course, I ran this on all 3 nodes!
    @@ -3263,8 +3263,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0: ~ % doas dmesg | grep UPS
    -ugen0.2: <American Power Conversion Back-UPS BX750MI> at usbus0
    +
    paul@f0: ~ % doas dmesg | grep UPS
    +ugen0.2: <American Power Conversion Back-UPS BX750MI> at usbus0
     

    apcupsd Installation


    @@ -3275,7 +3275,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0: ~ % doas install apcupsd
    +
    paul@f0: ~ % doas install apcupsd
     

    I have made the following modifications to the configuration file so that the UPS can be used via the USB interface:
    @@ -3284,29 +3284,29 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/usr/local/etc/apcupsd % diff -u apcupsd.conf.sample  apcupsd.conf
    ---- apcupsd.conf.sample 2024-11-01 16:40:42.000000000 +0200
    -+++ apcupsd.conf        2024-12-03 10:58:24.009501000 +0200
    -@@ -31,7 +31,7 @@
    - #     940-1524C, 940-0024G, 940-0095A, 940-0095B,
    - #     940-0095C, 940-0625A, M-04-02-2000
    - #
    --UPSCABLE smart
    -+UPSCABLE usb
    +
    paul@f0:/usr/local/etc/apcupsd % diff -u apcupsd.conf.sample  apcupsd.conf
    +--- apcupsd.conf.sample 2024-11-01 16:40:42.000000000 +0200
    ++++ apcupsd.conf        2024-12-03 10:58:24.009501000 +0200
    +@@ -31,7 +31,7 @@
    + #     940-1524C, 940-0024G, 940-0095A, 940-0095B,
    + #     940-0095C, 940-0625A, M-04-02-2000
    + #
    +-UPSCABLE smart
    ++UPSCABLE usb
     
    - # To get apcupsd to work, in addition to defining the cable
    - # above, you must also define a UPSTYPE, which corresponds to
    -@@ -88,8 +88,10 @@
    - #                            that apcupsd binds to that particular unit
    - #                            (helpful if you have more than one USB UPS).
    - #
    --UPSTYPE apcsmart
    --DEVICE /dev/usv
    -+UPSTYPE usb
    -+DEVICE
    + # To get apcupsd to work, in addition to defining the cable
    + # above, you must also define a UPSTYPE, which corresponds to
    +@@ -88,8 +88,10 @@
    + #                            that apcupsd binds to that particular unit
    + #                            (helpful if you have more than one USB UPS).
    + #
    +-UPSTYPE apcsmart
    +-DEVICE /dev/usv
    ++UPSTYPE usb
    ++DEVICE
     
    - # POLLTIME <int>
    - #   Interval (in seconds) at which apcupsd polls the UPS for status. This
    + # POLLTIME <int>
    + #   Interval (in seconds) at which apcupsd polls the UPS for status. This
     

    I left the remaining settings as the default ones; for example, the following are of main interest:
    @@ -3329,10 +3329,10 @@ MINUTES 3 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/usr/local/etc/apcupsd % doas sysrc apcupsd_enable=YES
    -apcupsd_enable:  -> YES
    -paul@f0:/usr/local/etc/apcupsd % doas service apcupsd start
    -Starting apcupsd.
    +
    paul@f0:/usr/local/etc/apcupsd % doas sysrc apcupsd_enable=YES
    +apcupsd_enable:  -> YES
    +paul@f0:/usr/local/etc/apcupsd % doas service apcupsd start
    +Starting apcupsd.
     

    UPS Connectivity Test


    @@ -3343,43 +3343,43 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % apcaccess
    -APC      : 001,035,0857
    -DATE     : 2025-01-26 14:43:27 +0200
    -HOSTNAME : f0.lan.buetow.org
    -VERSION  : 3.14.14 (31 May 2016) freebsd
    -UPSNAME  : f0.lan.buetow.org
    -CABLE    : USB Cable
    -DRIVER   : USB UPS Driver
    -UPSMODE  : Stand Alone
    -STARTTIME: 2025-01-26 14:43:25 +0200
    -MODEL    : Back-UPS BX750MI
    -STATUS   : ONLINE
    -LINEV    : 230.0 Volts
    -LOADPCT  : 4.0 Percent
    -BCHARGE  : 100.0 Percent
    -TIMELEFT : 65.3 Minutes
    -MBATTCHG : 5 Percent
    -MINTIMEL : 3 Minutes
    -MAXTIME  : 0 Seconds
    -SENSE    : Medium
    -LOTRANS  : 145.0 Volts
    -HITRANS  : 295.0 Volts
    -ALARMDEL : No alarm
    -BATTV    : 13.6 Volts
    -LASTXFER : Automatic or explicit self test
    -NUMXFERS : 0
    -TONBATT  : 0 Seconds
    -CUMONBATT: 0 Seconds
    -XOFFBATT : N/A
    -SELFTEST : NG
    -STATFLAG : 0x05000008
    -SERIALNO : 9B2414A03599
    -BATTDATE : 2001-01-01
    -NOMINV   : 230 Volts
    -NOMBATTV : 12.0 Volts
    -NOMPOWER : 410 Watts
    -END APC  : 2025-01-26 14:44:06 +0200
    +
    paul@f0:~ % apcaccess
    +APC      : 001,035,0857
    +DATE     : 2025-01-26 14:43:27 +0200
    +HOSTNAME : f0.lan.buetow.org
    +VERSION  : 3.14.14 (31 May 2016) freebsd
    +UPSNAME  : f0.lan.buetow.org
    +CABLE    : USB Cable
    +DRIVER   : USB UPS Driver
    +UPSMODE  : Stand Alone
    +STARTTIME: 2025-01-26 14:43:25 +0200
    +MODEL    : Back-UPS BX750MI
    +STATUS   : ONLINE
    +LINEV    : 230.0 Volts
    +LOADPCT  : 4.0 Percent
    +BCHARGE  : 100.0 Percent
    +TIMELEFT : 65.3 Minutes
    +MBATTCHG : 5 Percent
    +MINTIMEL : 3 Minutes
    +MAXTIME  : 0 Seconds
    +SENSE    : Medium
    +LOTRANS  : 145.0 Volts
    +HITRANS  : 295.0 Volts
    +ALARMDEL : No alarm
    +BATTV    : 13.6 Volts
    +LASTXFER : Automatic or explicit self test
    +NUMXFERS : 0
    +TONBATT  : 0 Seconds
    +CUMONBATT: 0 Seconds
    +XOFFBATT : N/A
    +SELFTEST : NG
    +STATFLAG : 0x05000008
    +SERIALNO : 9B2414A03599
    +BATTDATE : 2001-01-01
    +NOMINV   : 230 Volts
    +NOMBATTV : 12.0 Volts
    +NOMPOWER : 410 Watts
    +END APC  : 2025-01-26 14:44:06 +0200
     

    APC Info on Partner Nodes:


    @@ -3398,10 +3398,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f1:~ % apcaccess -h f0.lan.buetow.org | grep Percent
    -LOADPCT  : 12.0 Percent
    -BCHARGE  : 94.0 Percent
    -MBATTCHG : 5 Percent
    +
    paul@f1:~ % apcaccess -h f0.lan.buetow.org | grep Percent
    +LOADPCT  : 12.0 Percent
    +BCHARGE  : 94.0 Percent
    +MBATTCHG : 5 Percent
     

    But I want the daemon to be configured and enabled in such a way that it connects to the master UPS node (the one with the UPS connected via USB) so that it can also initiate a system shutdown when the UPS battery reaches low levels. For that, apcupsd itself needs to be aware of the UPS status.
    @@ -3412,52 +3412,52 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f2:/usr/local/etc/apcupsd % diff -u apcupsd.conf.sample apcupsd.conf
    ---- apcupsd.conf.sample 2024-11-01 16:40:42.000000000 +0200
    -+++ apcupsd.conf        2025-01-26 15:52:45.108469000 +0200
    -@@ -31,7 +31,7 @@
    - #     940-1524C, 940-0024G, 940-0095A, 940-0095B,
    - #     940-0095C, 940-0625A, M-04-02-2000
    - #
    --UPSCABLE smart
    -+UPSCABLE ether
    -
    - # To get apcupsd to work, in addition to defining the cable
    - # above, you must also define a UPSTYPE, which corresponds to
    -@@ -52,7 +52,6 @@
    - #                            Network Information Server. This is used if the
    - #                            UPS powering your computer is connected to a
    - #                            different computer for monitoring.
    --#
    - # snmp      hostname:port:vendor:community
    - #                            SNMP network link to an SNMP-enabled UPS device.
    - #                            Hostname is the ip address or hostname of the UPS
    -@@ -88,8 +87,8 @@
    - #                            that apcupsd binds to that particular unit
    - #                            (helpful if you have more than one USB UPS).
    - #
    --UPSTYPE apcsmart
    --DEVICE /dev/usv
    -+UPSTYPE net
    -+DEVICE f0.lan.buetow.org:3551
    -
    - # POLLTIME <int>
    - #   Interval (in seconds) at which apcupsd polls the UPS for status. This
    -@@ -147,12 +146,12 @@
    - # If during a power failure, the remaining battery percentage
    - # (as reported by the UPS) is below or equal to BATTERYLEVEL,
    - # apcupsd will initiate a system shutdown.
    --BATTERYLEVEL 5
    -+BATTERYLEVEL 10
    -
    - # If during a power failure, the remaining runtime in minutes
    - # (as calculated internally by the UPS) is below or equal to MINUTES,
    - # apcupsd, will initiate a system shutdown.
    --MINUTES 3
    -+MINUTES 6
    -
    - # If during a power failure, the UPS has run on batteries for TIMEOUT
    - # many seconds or longer, apcupsd will initiate a system shutdown.
    +
    paul@f2:/usr/local/etc/apcupsd % diff -u apcupsd.conf.sample apcupsd.conf
    +--- apcupsd.conf.sample 2024-11-01 16:40:42.000000000 +0200
    ++++ apcupsd.conf        2025-01-26 15:52:45.108469000 +0200
    +@@ -31,7 +31,7 @@
    + #     940-1524C, 940-0024G, 940-0095A, 940-0095B,
    + #     940-0095C, 940-0625A, M-04-02-2000
    + #
    +-UPSCABLE smart
    ++UPSCABLE ether
    +
    + # To get apcupsd to work, in addition to defining the cable
    + # above, you must also define a UPSTYPE, which corresponds to
    +@@ -52,7 +52,6 @@
    + #                            Network Information Server. This is used if the
    + #                            UPS powering your computer is connected to a
    + #                            different computer for monitoring.
    +-#
    + # snmp      hostname:port:vendor:community
    + #                            SNMP network link to an SNMP-enabled UPS device.
    + #                            Hostname is the ip address or hostname of the UPS
    +@@ -88,8 +87,8 @@
    + #                            that apcupsd binds to that particular unit
    + #                            (helpful if you have more than one USB UPS).
    + #
    +-UPSTYPE apcsmart
    +-DEVICE /dev/usv
    ++UPSTYPE net
    ++DEVICE f0.lan.buetow.org:3551
    +
    + # POLLTIME <int>
    + #   Interval (in seconds) at which apcupsd polls the UPS for status. This
    +@@ -147,12 +146,12 @@
    + # If during a power failure, the remaining battery percentage
    + # (as reported by the UPS) is below or equal to BATTERYLEVEL,
    + # apcupsd will initiate a system shutdown.
    +-BATTERYLEVEL 5
    ++BATTERYLEVEL 10
    +
    + # If during a power failure, the remaining runtime in minutes
    + # (as calculated internally by the UPS) is below or equal to MINUTES,
    + # apcupsd, will initiate a system shutdown.
    +-MINUTES 3
    ++MINUTES 6
    +
    + # If during a power failure, the UPS has run on batteries for TIMEOUT
    + # many seconds or longer, apcupsd will initiate a system shutdown.
     
     
    So I also ran the following commands on f1 and f2:
    @@ -3466,10 +3466,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f1:/usr/local/etc/apcupsd % doas sysrc apcupsd_enable=YES
    -apcupsd_enable:  -> YES
    -paul@f1:/usr/local/etc/apcupsd % doas service apcupsd start
    -Starting apcupsd.
    +
    paul@f1:/usr/local/etc/apcupsd % doas sysrc apcupsd_enable=YES
    +apcupsd_enable:  -> YES
    +paul@f1:/usr/local/etc/apcupsd % doas service apcupsd start
    +Starting apcupsd.
     

    And then I was able to connect to localhost via the apcaccess command:
    @@ -3478,10 +3478,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f1:~ % doas apcaccess | grep Percent
    -LOADPCT  : 5.0 Percent
    -BCHARGE  : 95.0 Percent
    -MBATTCHG : 5 Percent
    +
    paul@f1:~ % doas apcaccess | grep Percent
    +LOADPCT  : 5.0 Percent
    +BCHARGE  : 95.0 Percent
    +MBATTCHG : 5 Percent
     

    Power outage simulation


    @@ -3503,8 +3503,8 @@ Power failure. Running on UPS batteries. by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:/usr/local/etc/apcupsd % apcaccess -p TIMELEFT
    -63.9 Minutes
    +
    paul@f0:/usr/local/etc/apcupsd % apcaccess -p TIMELEFT
    +63.9 Minutes
     

    And after around one hour (f1 and f2 a bit earlier, f0 a bit later due to the different BATTERYLEVEL and MINUTES settings outlined earlier), the following broadcast was sent out:
    @@ -4272,9 +4272,9 @@ Jan 26 17:36:32 f2 apcupsd[2159]: apcupsd shutdown succeeded by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    [paul@earth]~/Downloads% sudo dd \
    -  if=FreeBSD-14.1-RELEASE-amd64-bootonly.iso \
    -  of=/dev/sda conv=sync
    +
    [paul@earth]~/Downloads% sudo dd \
    +  if=FreeBSD-14.1-RELEASE-amd64-bootonly.iso \
    +  of=/dev/sda conv=sync
     

    Next, I plugged the Beelinks (one after another) into my monitor via HDMI (the resolution of the FreeBSD text console seems strangely stretched, as I am using the LG Dual Up monitor), connected Ethernet, an external USB keyboard, and the FreeBSD USB stick, and booted the devices up. With F7, I entered the boot menu and selected the USB stick for the FreeBSD installation.
    @@ -4300,9 +4300,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # freebsd-update fetch
    -root@f0:~ # freebsd-update install
    -root@f0:~ # freebsd-update reboot
    +
    root@f0:~ # freebsd-update fetch
    +root@f0:~ # freebsd-update install
    +root@f0:~ # freebsd-update reboot
     

    I also added the following entries for the three FreeBSD boxes to the /etc/hosts file:
    @@ -4311,11 +4311,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # cat <<END >>/etc/hosts
    -192.168.1.130 f0 f0.lan f0.lan.buetow.org
    -192.168.1.131 f1 f1.lan f1.lan.buetow.org
    -192.168.1.132 f2 f2.lan f2.lan.buetow.org
    -END
    +
    root@f0:~ # cat <<END >>/etc/hosts
    +192.168.1.130 f0 f0.lan f0.lan.buetow.org
    +192.168.1.131 f1 f1.lan f1.lan.buetow.org
    +192.168.1.132 f2 f2.lan f2.lan.buetow.org
    +END
     

    You might wonder why bother using the hosts file? Why not use DNS properly? The reason is simplicity. I don't manage 100 hosts, only a few here and there. Having an OpenWRT router in my home, I could also configure everything there, but maybe I'll do that later. For now, keep it simple and straightforward.
    @@ -4328,7 +4328,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # pkg install helix doas zfs-periodic uptimed
    +
    root@f0:~ # pkg install helix doas zfs-periodic uptimed
     

    Helix editor


    @@ -4345,7 +4345,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # cp /usr/local/etc/doas.conf.sample /usr/local/etc/doas.conf
    +
    root@f0:~ # cp /usr/local/etc/doas.conf.sample /usr/local/etc/doas.conf
     

    https://man.openbsd.org/doas
    @@ -4358,17 +4358,17 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # cat <<END >>/etc/periodic.conf
    -daily_zfs_snapshot_enable="YES"
    -daily_zfs_snapshot_pools="zroot"
    -daily_zfs_snapshot_keep="7"
    -weekly_zfs_snapshot_enable="YES"
    -weekly_zfs_snapshot_pools="zroot"
    -weekly_zfs_snapshot_keep="5"
    -monthly_zfs_snapshot_enable="YES"
    -monthly_zfs_snapshot_pools="zroot"
    -monthly_zfs_snapshot_keep="6"
    -END
    +
    root@f0:~ # cat <<END >>/etc/periodic.conf
    +daily_zfs_snapshot_enable="YES"
    +daily_zfs_snapshot_pools="zroot"
    +daily_zfs_snapshot_keep="7"
    +weekly_zfs_snapshot_enable="YES"
    +weekly_zfs_snapshot_pools="zroot"
    +weekly_zfs_snapshot_keep="5"
    +monthly_zfs_snapshot_enable="YES"
    +monthly_zfs_snapshot_pools="zroot"
    +monthly_zfs_snapshot_keep="6"
    +END
     

    https://github.com/ross/zfs-periodic
    @@ -4381,9 +4381,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # cp /usr/local/mimecast/etc/uptimed.conf-dist \
    -  /usr/local/mimecast/etc/uptimed.conf 
    -root@f0:~ # hx /usr/local/mimecast/etc/uptimed.conf
    +
    root@f0:~ # cp /usr/local/mimecast/etc/uptimed.conf-dist \
    +  /usr/local/mimecast/etc/uptimed.conf 
    +root@f0:~ # hx /usr/local/mimecast/etc/uptimed.conf
     

    In the Helix editor session, I changed LOG_MAXIMUM_ENTRIES to 0 to keep all uptime entries forever and not cut off at 50 (the default config). After that, I enabled and started uptimed:
    @@ -4392,8 +4392,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    root@f0:~ # service uptimed enable
    -root@f0:~ # service uptimed start
    +
    root@f0:~ # service uptimed enable
    +root@f0:~ # service uptimed start
     

    To check the current uptime stats, I can now run uprecords:
    @@ -4402,15 +4402,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
     root@f0:~ # uprecords
    -     #               Uptime | System                                     Boot up
    -----------------------------+---------------------------------------------------
    -->   1     0 days, 00:07:34 | FreeBSD 14.1-RELEASE      Mon Dec  2 12:21:44 2024
    -----------------------------+---------------------------------------------------
    -NewRec     0 days, 00:07:33 | since                     Mon Dec  2 12:21:44 2024
    -    up     0 days, 00:07:34 | since                     Mon Dec  2 12:21:44 2024
    -  down     0 days, 00:00:00 | since                     Mon Dec  2 12:21:44 2024
    -   %up              100.000 | since                     Mon Dec  2 12:21:44 2024
    +
     root@f0:~ # uprecords
    +     #               Uptime | System                                     Boot up
    +----------------------------+---------------------------------------------------
    +->   1     0 days, 00:07:34 | FreeBSD 14.1-RELEASE      Mon Dec  2 12:21:44 2024
    +----------------------------+---------------------------------------------------
    +NewRec     0 days, 00:07:33 | since                     Mon Dec  2 12:21:44 2024
    +    up     0 days, 00:07:34 | since                     Mon Dec  2 12:21:44 2024
    +  down     0 days, 00:00:00 | since                     Mon Dec  2 12:21:44 2024
    +   %up              100.000 | since                     Mon Dec  2 12:21:44 2024
     

    This is how I track the uptimes for all of my host:
    @@ -4428,17 +4428,17 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % ifconfig re0
    -re0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
    -        options=8209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE>
    -        ether e8:ff:1e:d7:1c:ac
    -        inet 192.168.1.130 netmask 0xffffff00 broadcast 192.168.1.255
    -        inet6 fe80::eaff:1eff:fed7:1cac%re0 prefixlen 64 scopeid 0x1
    -        inet6 fd22:c702:acb7:0:eaff:1eff:fed7:1cac prefixlen 64 detached autoconf
    -        inet6 2a01:5a8:304:1d5c:eaff:1eff:fed7:1cac prefixlen 64 autoconf pltime 10800 vltime 14400
    -        media: Ethernet autoselect (1000baseT <full-duplex>)
    -        status: active
    -        nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
    +
    paul@f0:~ % ifconfig re0
    +re0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
    +        options=8209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE>
    +        ether e8:ff:1e:d7:1c:ac
    +        inet 192.168.1.130 netmask 0xffffff00 broadcast 192.168.1.255
    +        inet6 fe80::eaff:1eff:fed7:1cac%re0 prefixlen 64 scopeid 0x1
    +        inet6 fd22:c702:acb7:0:eaff:1eff:fed7:1cac prefixlen 64 detached autoconf
    +        inet6 2a01:5a8:304:1d5c:eaff:1eff:fed7:1cac prefixlen 64 autoconf pltime 10800 vltime 14400
    +        media: Ethernet autoselect (1000baseT <full-duplex>)
    +        status: active
    +        nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
     

    RAM


    @@ -4449,8 +4449,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % sysctl hw.physmem
    -hw.physmem: 16902905856
    +
    paul@f0:~ % sysctl hw.physmem
    +hw.physmem: 16902905856
     
     

    @@ -4462,11 +4462,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % sysctl dev.cpu | grep freq:
    -dev.cpu.3.freq: 705
    -dev.cpu.2.freq: 705
    -dev.cpu.1.freq: 604
    -dev.cpu.0.freq: 604
    +
    paul@f0:~ % sysctl dev.cpu | grep freq:
    +dev.cpu.3.freq: 705
    +dev.cpu.2.freq: 705
    +dev.cpu.1.freq: 604
    +dev.cpu.0.freq: 604
     

    CPU throttling


    @@ -4477,14 +4477,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    paul@f0:~ % doas pkg install ubench
    -paul@f0:~ % rehash # For tcsh to find the newly installed command
    -paul@f0:~ % ubench &
    -paul@f0:~ % sysctl dev.cpu | grep freq:
    -dev.cpu.3.freq: 2922
    -dev.cpu.2.freq: 2922
    -dev.cpu.1.freq: 2923
    -dev.cpu.0.freq: 2922
    +
    paul@f0:~ % doas pkg install ubench
    +paul@f0:~ % rehash # For tcsh to find the newly installed command
    +paul@f0:~ % ubench &
    +paul@f0:~ % sysctl dev.cpu | grep freq:
    +dev.cpu.3.freq: 2922
    +dev.cpu.2.freq: 2922
    +dev.cpu.1.freq: 2923
    +dev.cpu.0.freq: 2922
     

    Idle, all three Beelinks plus the switch consumed 26.2W. But with ubench stressing all the CPUs, it went up to 38.8W.
    @@ -4948,7 +4948,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    declare -xr HTML_THEME_DIR=./extras/html/themes/simple
    +
    declare -xr HTML_THEME_DIR=./extras/html/themes/simple
     

    To customize the theme or create your own, simply copy the theme directory and modify it as needed. This makes it also much easier to switch between layouts.
    @@ -5582,52 +5582,52 @@ WHOA!! ( o.o ) by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ❯ traceroute -m 60 bad.horse
    -traceroute to bad.horse (162.252.205.157), 60 hops max, 60 byte packets
    - 1  _gateway (192.168.1.1)  5.237 ms  5.264 ms  6.009 ms
    - 2  77-85-0-2.ip.btc-net.bg (77.85.0.2)  8.753 ms  7.112 ms  8.336 ms
    - 3  212-39-69-103.ip.btc-net.bg (212.39.69.103)  9.434 ms  9.268 ms  9.986 ms
    - 4  * * *
    - 5  xe-1-2-0.mpr1.fra4.de.above.net (80.81.194.26)  39.812 ms  39.030 ms  39.772 ms
    - 6  * ae12.cs1.fra6.de.eth.zayo.com (64.125.26.172)  123.576 ms *
    - 7  * * *
    - 8  * * *
    - 9  ae10.cr1.lhr15.uk.eth.zayo.com (64.125.29.17)  119.097 ms  119.478 ms  120.767 ms
    -10  ae2.cr1.lhr11.uk.zip.zayo.com (64.125.24.140)  120.398 ms  121.147 ms  120.948 ms
    -11  * * *
    -12  ae25.mpr1.yyz1.ca.zip.zayo.com (64.125.23.117)  145.072 ms *  181.773 ms
    -13  ae5.mpr1.tor3.ca.zip.zayo.com (64.125.23.118)  168.239 ms  168.158 ms  168.137 ms
    -14  64.124.217.237.IDIA-265104-ZYO.zip.zayo.com (64.124.217.237)  168.026 ms  167.999 ms  165.451 ms
    -15  * * *
    -16  t00.toroc1.on.ca.sn11.net (162.252.204.2)  131.598 ms  131.308 ms  131.482 ms
    -17  bad.horse (162.252.205.130)  131.430 ms  145.914 ms  130.514 ms
    -18  bad.horse (162.252.205.131)  136.634 ms  145.295 ms  135.631 ms
    -19  bad.horse (162.252.205.132)  139.158 ms  148.363 ms  138.934 ms
    -20  bad.horse (162.252.205.133)  145.395 ms  148.054 ms  147.140 ms
    -21  he.rides.across.the.nation (162.252.205.134)  149.687 ms  147.731 ms  150.135 ms
    -22  the.thoroughbred.of.sin (162.252.205.135)  156.644 ms  155.155 ms  156.447 ms
    -23  he.got.the.application (162.252.205.136)  161.187 ms  162.318 ms  162.674 ms
    -24  that.you.just.sent.in (162.252.205.137)  166.763 ms  166.675 ms  164.243 ms
    -25  it.needs.evaluation (162.252.205.138)  172.073 ms  171.919 ms  171.390 ms
    -26  so.let.the.games.begin (162.252.205.139)  175.386 ms  174.180 ms  175.965 ms
    -27  a.heinous.crime (162.252.205.140)  180.857 ms  180.766 ms  180.192 ms
    -28  a.show.of.force (162.252.205.141)  187.942 ms  186.669 ms  186.986 ms
    -29  a.murder.would.be.nice.of.course (162.252.205.142)  191.349 ms  191.939 ms  190.740 ms
    -30  bad.horse (162.252.205.143)  195.425 ms  195.716 ms  196.186 ms
    -31  bad.horse (162.252.205.144)  199.238 ms  200.620 ms  200.318 ms
    -32  bad.horse (162.252.205.145)  207.554 ms  206.729 ms  205.201 ms
    -33  he-s.bad (162.252.205.146)  211.087 ms  211.649 ms  211.712 ms
    -34  the.evil.league.of.evil (162.252.205.147)  212.657 ms  216.777 ms  216.589 ms
    -35  is.watching.so.beware (162.252.205.148)  220.911 ms  220.326 ms  221.961 ms
    -36  the.grade.that.you.receive (162.252.205.149)  225.384 ms  225.696 ms  225.640 ms
    -37  will.be.your.last.we.swear (162.252.205.150)  232.312 ms  230.989 ms  230.919 ms
    -38  so.make.the.bad.horse.gleeful (162.252.205.151)  235.761 ms  235.291 ms  235.585 ms
    -39  or.he-ll.make.you.his.mare (162.252.205.152)  241.350 ms  239.407 ms  238.394 ms
    -40  o_o (162.252.205.153)  246.154 ms  247.650 ms  247.110 ms
    -41  you-re.saddled.up (162.252.205.154)  250.925 ms  250.401 ms  250.619 ms
    -42  there-s.no.recourse (162.252.205.155)  256.071 ms  251.154 ms  255.340 ms
    -43  it-s.hi-ho.silver (162.252.205.156)  260.152 ms  261.775 ms  261.544 ms
    -44  signed.bad.horse (162.252.205.157)  262.430 ms  261.410 ms  261.365 ms
    +
    ❯ traceroute -m 60 bad.horse
    +traceroute to bad.horse (162.252.205.157), 60 hops max, 60 byte packets
    + 1  _gateway (192.168.1.1)  5.237 ms  5.264 ms  6.009 ms
    + 2  77-85-0-2.ip.btc-net.bg (77.85.0.2)  8.753 ms  7.112 ms  8.336 ms
    + 3  212-39-69-103.ip.btc-net.bg (212.39.69.103)  9.434 ms  9.268 ms  9.986 ms
    + 4  * * *
    + 5  xe-1-2-0.mpr1.fra4.de.above.net (80.81.194.26)  39.812 ms  39.030 ms  39.772 ms
    + 6  * ae12.cs1.fra6.de.eth.zayo.com (64.125.26.172)  123.576 ms *
    + 7  * * *
    + 8  * * *
    + 9  ae10.cr1.lhr15.uk.eth.zayo.com (64.125.29.17)  119.097 ms  119.478 ms  120.767 ms
    +10  ae2.cr1.lhr11.uk.zip.zayo.com (64.125.24.140)  120.398 ms  121.147 ms  120.948 ms
    +11  * * *
    +12  ae25.mpr1.yyz1.ca.zip.zayo.com (64.125.23.117)  145.072 ms *  181.773 ms
    +13  ae5.mpr1.tor3.ca.zip.zayo.com (64.125.23.118)  168.239 ms  168.158 ms  168.137 ms
    +14  64.124.217.237.IDIA-265104-ZYO.zip.zayo.com (64.124.217.237)  168.026 ms  167.999 ms  165.451 ms
    +15  * * *
    +16  t00.toroc1.on.ca.sn11.net (162.252.204.2)  131.598 ms  131.308 ms  131.482 ms
    +17  bad.horse (162.252.205.130)  131.430 ms  145.914 ms  130.514 ms
    +18  bad.horse (162.252.205.131)  136.634 ms  145.295 ms  135.631 ms
    +19  bad.horse (162.252.205.132)  139.158 ms  148.363 ms  138.934 ms
    +20  bad.horse (162.252.205.133)  145.395 ms  148.054 ms  147.140 ms
    +21  he.rides.across.the.nation (162.252.205.134)  149.687 ms  147.731 ms  150.135 ms
    +22  the.thoroughbred.of.sin (162.252.205.135)  156.644 ms  155.155 ms  156.447 ms
    +23  he.got.the.application (162.252.205.136)  161.187 ms  162.318 ms  162.674 ms
    +24  that.you.just.sent.in (162.252.205.137)  166.763 ms  166.675 ms  164.243 ms
    +25  it.needs.evaluation (162.252.205.138)  172.073 ms  171.919 ms  171.390 ms
    +26  so.let.the.games.begin (162.252.205.139)  175.386 ms  174.180 ms  175.965 ms
    +27  a.heinous.crime (162.252.205.140)  180.857 ms  180.766 ms  180.192 ms
    +28  a.show.of.force (162.252.205.141)  187.942 ms  186.669 ms  186.986 ms
    +29  a.murder.would.be.nice.of.course (162.252.205.142)  191.349 ms  191.939 ms  190.740 ms
    +30  bad.horse (162.252.205.143)  195.425 ms  195.716 ms  196.186 ms
    +31  bad.horse (162.252.205.144)  199.238 ms  200.620 ms  200.318 ms
    +32  bad.horse (162.252.205.145)  207.554 ms  206.729 ms  205.201 ms
    +33  he-s.bad (162.252.205.146)  211.087 ms  211.649 ms  211.712 ms
    +34  the.evil.league.of.evil (162.252.205.147)  212.657 ms  216.777 ms  216.589 ms
    +35  is.watching.so.beware (162.252.205.148)  220.911 ms  220.326 ms  221.961 ms
    +36  the.grade.that.you.receive (162.252.205.149)  225.384 ms  225.696 ms  225.640 ms
    +37  will.be.your.last.we.swear (162.252.205.150)  232.312 ms  230.989 ms  230.919 ms
    +38  so.make.the.bad.horse.gleeful (162.252.205.151)  235.761 ms  235.291 ms  235.585 ms
    +39  or.he-ll.make.you.his.mare (162.252.205.152)  241.350 ms  239.407 ms  238.394 ms
    +40  o_o (162.252.205.153)  246.154 ms  247.650 ms  247.110 ms
    +41  you-re.saddled.up (162.252.205.154)  250.925 ms  250.401 ms  250.619 ms
    +42  there-s.no.recourse (162.252.205.155)  256.071 ms  251.154 ms  255.340 ms
    +43  it-s.hi-ho.silver (162.252.205.156)  260.152 ms  261.775 ms  261.544 ms
    +44  signed.bad.horse (162.252.205.157)  262.430 ms  261.410 ms  261.365 ms
     

    2. ASCII cinema


    @@ -5655,20 +5655,20 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #include <stdio.h>
    +
    #include <stdio.h>
     
    -int main(void) {
    -  int array[5] = { 1, 2, 3, 4, 5 };
    +int main(void) {
    +  int array[5] = { 1, 2, 3, 4, 5 };
     
    -  for (int i = 0; i < 5; i++)
    -    printf("%d\n", array[i]);
    +  for (int i = 0; i < 5; i++)
    +    printf("%d\n", array[i]);
     
    -  for (int i = 0; i < 5; i++)
    -    printf("%d\n", i[array]);
    +  for (int i = 0; i < 5; i++)
    +    printf("%d\n", i[array]);
     
    -  for (int i = 0; i < 5; i++)
    -    printf("%d\n", *(i + array));
    -}
    +  for (int i = 0; i < 5; i++)
    +    printf("%d\n", *(i + array));
    +}
     

    5. Variables with prefix $


    @@ -5679,20 +5679,20 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #include <stdio.h>
    +
    #include <stdio.h>
     
    -int main(void) {
    -  int $array[5] = { 1, 2, 3, 4, 5 };
    +int main(void) {
    +  int $array[5] = { 1, 2, 3, 4, 5 };
     
    -  for (int $i = 0; $i < 5; $i++)
    -    printf("%d\n", $array[$i]);
    +  for (int $i = 0; $i < 5; $i++)
    +    printf("%d\n", $array[$i]);
     
    -  for (int $i = 0; $i < 5; $i++)
    -    printf("%d\n", $i[$array]);
    +  for (int $i = 0; $i < 5; $i++)
    +    printf("%d\n", $i[$array]);
     
    -  for (int $i = 0; $i < 5; $i++)
    -    printf("%d\n", *($i + $array));
    -}
    +  for (int $i = 0; $i < 5; $i++)
    +    printf("%d\n", *($i + $array));
    +}
     

    6. Object oriented shell scripts using ksh


    @@ -5703,40 +5703,40 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/ksh93
    - 
    -typeset -T Point_t=(
    -    integer -h 'x coordinate' x=0
    -    integer -h 'y coordinate' y=0
    -    typeset -h 'point color'  color="red"
    +
    #!/usr/bin/ksh93
    + 
    +typeset -T Point_t=(
    +    integer -h 'x coordinate' x=0
    +    integer -h 'y coordinate' y=0
    +    typeset -h 'point color'  color="red"
     
    -    function getcolor {
    -        print -r ${_.color}
    -    }
    +    function getcolor {
    +        print -r ${_.color}
    +    }
     
    -    function setcolor {
    -        _.color=$1
    -    }
    +    function setcolor {
    +        _.color=$1
    +    }
     
    -    setxy() {
    -        _.x=$1; _.y=$2
    -    }
    +    setxy() {
    +        _.x=$1; _.y=$2
    +    }
     
    -    getxy() {
    -        print -r "(${_.x},${_.y})"
    -    }
    -)
    - 
    -Point_t point
    - 
    -echo "Initial coordinates are (${point.x},${point.y}). Color is ${point.color}"
    - 
    -point.setxy 5 6
    -point.setcolor blue
    - 
    -echo "New coordinates are ${point.getxy}. Color is ${point.getcolor}"
    - 
    -exit 0
    +    getxy() {
    +        print -r "(${_.x},${_.y})"
    +    }
    +)
    + 
    +Point_t point
    + 
    +echo "Initial coordinates are (${point.x},${point.y}). Color is ${point.color}"
    + 
    +point.setxy 5 6
    +point.setcolor blue
    + 
    +echo "New coordinates are ${point.getxy}. Color is ${point.getcolor}"
    + 
    +exit 0
     

    Using types to create object oriented Korn shell 93 scripts
    @@ -5749,18 +5749,18 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    package main
    +
    package main
     
    -import "fmt"
    +import "fmt"
     
    -func main() {
    -	var i int
    -	f := func() *int {
    -		return &i
    -	}
    -	*f()++
    -	fmt.Println(i)
    -}
    +func main() {
    +	var i int
    +	f := func() *int {
    +		return &i
    +	}
    +	*f()++
    +	fmt.Println(i)
    +}
     

    Go playground
    @@ -6015,13 +6015,13 @@ jgs `-=========-`() by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    alias tm=tmux
    -alias tl='tmux list-sessions'
    -alias tn=tmux::new
    -alias ta=tmux::attach
    -alias tx=tmux::remote
    -alias ts=tmux::search
    -alias tssh=tmux::cluster_ssh
    +
    alias tm=tmux
    +alias tl='tmux list-sessions'
    +alias tn=tmux::new
    +alias ta=tmux::attach
    +alias tx=tmux::remote
    +alias ts=tmux::search
    +alias tssh=tmux::cluster_ssh
     

    Note all tmux::...; those are custom shell functions doing certain things, and they aren't part of the Tmux distribution. But let's run through every aliases one by one.
    @@ -6036,23 +6036,23 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    # Create new session and if alread exists attach to it
    -tmux::new () {
    -    readonly session=$1
    -    local date=date
    -    if where gdate &>/dev/null; then
    -        date=gdate
    -    fi
    +
    # Create new session and if alread exists attach to it
    +tmux::new () {
    +    readonly session=$1
    +    local date=date
    +    if where gdate &>/dev/null; then
    +        date=gdate
    +    fi
     
    -    tmux::cleanup_default
    -    if [ -z "$session" ]; then
    -        tmux::new T$($date +%s)
    -    else
    -        tmux new-session -d -s $session
    -        tmux -2 attach-session -t $session || tmux -2 switch-client -t $session
    -    fi
    -}
    -alias tn=tmux::new
    +    tmux::cleanup_default
    +    if [ -z "$session" ]; then
    +        tmux::new T$($date +%s)
    +    else
    +        tmux new-session -d -s $session
    +        tmux -2 attach-session -t $session || tmux -2 switch-client -t $session
    +    fi
    +}
    +alias tn=tmux::new
     

    There is a lot going on here. Let's have a detailed look at what it is doing. As a note, the function relies on GNU Date, so MacOS is looking for the gdate commands to be available. Otherwise, it will fall back to date. You need to install GNU Date for Mac, as it isn't installed by default there. As I use Fedora Linux on my personal Laptop and a MacBook for work, I have to make it work for both.
    @@ -6067,14 +6067,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::cleanup_default () {
    -    local s
    -    tmux list-sessions | grep '^T.*: ' | grep -F -v attached |
    -    cut -d: -f1 | while read -r s; do
    -        echo "Killing $s"
    -        tmux kill-session -t "$s"
    -    done
    -}
    +
    tmux::cleanup_default () {
    +    local s
    +    tmux list-sessions | grep '^T.*: ' | grep -F -v attached |
    +    cut -d: -f1 | while read -r s; do
    +        echo "Killing $s"
    +        tmux kill-session -t "$s"
    +    done
    +}
     

    The cleanup function kills all open Tmux sessions that haven't been renamed properly yet—but only if they aren't attached (e.g., don't run in the foreground in any terminal). Cleaning them up automatically keeps my Tmux sessions as neat and tidy as possible.
    @@ -6091,16 +6091,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::attach () {
    -    readonly session=$1
    +
    tmux::attach () {
    +    readonly session=$1
     
    -    if [ -z "$session" ]; then
    -        tmux attach-session || tmux::new
    -    else
    -        tmux attach-session -t $session || tmux::new $session
    -    fi
    -}
    -alias ta=tmux::attach
    +    if [ -z "$session" ]; then
    +        tmux attach-session || tmux::new
    +    else
    +        tmux attach-session -t $session || tmux::new $session
    +    fi
    +}
    +alias ta=tmux::attach
     

    If no session is specified (as the argument of the function), it will try to attach to the first open session. If no Tmux server is running, it will create a new one with tmux::new. Otherwise, with a session name given as the argument, it will attach to it. If unsuccessful (e.g., the session doesn't exist), it will be created and attached to.
    @@ -6113,12 +6113,12 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::remote () {
    -    readonly server=$1
    -    tmux new -s $server "ssh -t $server 'tmux attach-session || tmux'" || \
    -        tmux attach-session -d -t $server
    -}
    -alias tr=tmux::remote
    +
    tmux::remote () {
    +    readonly server=$1
    +    tmux new -s $server "ssh -t $server 'tmux attach-session || tmux'" || \
    +        tmux attach-session -d -t $server
    +}
    +alias tr=tmux::remote
     

    Change of the Tmux prefix for better nesting


    @@ -6141,15 +6141,15 @@ set-option -g prefix C-g by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::search () {
    -    local -r session=$(tmux list-sessions | fzf | cut -d: -f1)
    -    if [ -z "$TMUX" ]; then
    -        tmux attach-session -t $session
    -    else
    -        tmux switch -t $session
    -    fi
    -}
    -alias ts=tmux::search
    +
    tmux::search () {
    +    local -r session=$(tmux list-sessions | fzf | cut -d: -f1)
    +    if [ -z "$TMUX" ]; then
    +        tmux attach-session -t $session
    +    else
    +        tmux switch -t $session
    +    fi
    +}
    +alias ts=tmux::search
     

    All it does is list all currently open sessions in fzf, where one of them can be searched and selected through fuzzy find, and then either switch (if already inside a session) to the other session or attach to the other session (if not yet in Tmux).
    @@ -6176,15 +6176,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::cluster_ssh () {
    -    if [ -f "$1" ]; then
    -        tmux::tssh_from_file $1
    -        return
    -    fi
    +
    tmux::cluster_ssh () {
    +    if [ -f "$1" ]; then
    +        tmux::tssh_from_file $1
    +        return
    +    fi
     
    -    tmux::tssh_from_argument $@
    -}
    -alias tssh=tmux::cluster_ssh
    +    tmux::tssh_from_argument $@
    +}
    +alias tssh=tmux::cluster_ssh
     

    This function is just a wrapper around the more complex tmux::tssh_from_file and tmux::tssh_from_argument functions, as you have learned already. Most of the magic happens there.
    @@ -6197,23 +6197,23 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::tssh_from_argument () {
    -    local -r session=$1; shift
    -    local first_server=$1; shift
    +
    tmux::tssh_from_argument () {
    +    local -r session=$1; shift
    +    local first_server=$1; shift
     
    -    tmux new-session -d -s $session "ssh -t $first_server"
    -    if ! tmux list-session | grep "^$session:"; then
    -        echo "Could not create session $session"
    -        return 2
    -    fi
    +    tmux new-session -d -s $session "ssh -t $first_server"
    +    if ! tmux list-session | grep "^$session:"; then
    +        echo "Could not create session $session"
    +        return 2
    +    fi
     
    -    for server in "${@[@]}"; do
    -        tmux split-window -t $session "tmux select-layout tiled; ssh -t $server"
    -    done
    +    for server in "${@[@]}"; do
    +        tmux split-window -t $session "tmux select-layout tiled; ssh -t $server"
    +    done
     
    -    tmux setw -t $session synchronize-panes on
    -    tmux -2 attach-session -t $session | tmux -2 switch-client -t $session
    -}
    +    tmux setw -t $session synchronize-panes on
    +    tmux -2 attach-session -t $session | tmux -2 switch-client -t $session
    +}
     

    It expects at least two arguments. The first argument is the session name to create for the clustered SSH session. All other arguments are server hostnames or FQDNs to which to connect. The first one is used to make the initial session. All remaining ones are added to that session with tmux split-window -t $session.... At the end, we enable synchronized panes by default, so whenever you type, the commands will be sent to every SSH connection, thus allowing the neat ClusterSSH feature to run commands on multiple servers simultaneously. Once done, we attach (or switch, if already in Tmux) to it.
    @@ -6233,12 +6233,12 @@ bind-key P setw synchronize-panes on by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    tmux::tssh_from_file () {
    -    local -r serverlist=$1; shift
    -    local -r session=$(basename $serverlist | cut -d. -f1)
    +
    tmux::tssh_from_file () {
    +    local -r serverlist=$1; shift
    +    local -r session=$(basename $serverlist | cut -d. -f1)
     
    -    tmux::tssh_from_argument $session $(awk '{ print $1} ' $serverlist | sed 's/.lan./.lan/g')
    -}
    +    tmux::tssh_from_argument $session $(awk '{ print $1} ' $serverlist | sed 's/.lan./.lan/g')
    +}
     

    tssh examples


    @@ -6586,12 +6586,12 @@ Art by Laura Brown by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    Cluster :UK, :uk01 do
    -  Customer.C1A1.segments.volumes.each do |volume|
    -    puts volume.usage_stats
    -    volume.move_off! if volume.over_subscribed?
    -  end
    -end
    +
    Cluster :UK, :uk01 do
    +  Customer.C1A1.segments.volumes.each do |volume|
    +    puts volume.usage_stats
    +    volume.move_off! if volume.over_subscribed?
    +  end
    +end
     

    I am abandoning this project because my workplace has stopped the annual pet project competition, and I have other more important projects to work on at the moment.
    @@ -6967,38 +6967,38 @@ _____|_:_:_| (o)-(o) |_:_:_|--'`-. ,--. ksh under-water (((\'/ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/bin/ksh
    +
    #!/bin/ksh
     
    -ZONES_DIR=/var/nsd/zones/master/
    -DEFAULT_MASTER=fishfinger.buetow.org
    -DEFAULT_STANDBY=blowfish.buetow.org
    +ZONES_DIR=/var/nsd/zones/master/
    +DEFAULT_MASTER=fishfinger.buetow.org
    +DEFAULT_STANDBY=blowfish.buetow.org
     
    -determine_master_and_standby () {
    -    local master=$DEFAULT_MASTER
    -    local standby=$DEFAULT_STANDBY
    +determine_master_and_standby () {
    +    local master=$DEFAULT_MASTER
    +    local standby=$DEFAULT_STANDBY
     
    -    .
    -    .
    -    .
    -    
    -    local -i health_ok=1
    -    if ! ftp -4 -o - https://$master/index.txt | grep -q "Welcome to $master"; then
    -        echo "https://$master/index.txt IPv4 health check failed"
    -        health_ok=0
    -    elif ! ftp -6 -o - https://$master/index.txt | grep -q "Welcome to $master"; then
    -        echo "https://$master/index.txt IPv6 health check failed"
    -        health_ok=0
    -    fi
    -    if [ $health_ok -eq 0 ]; then
    -        local tmp=$master
    -        master=$standby
    -        standby=$tmp
    -    fi
    +    .
    +    .
    +    .
    +    
    +    local -i health_ok=1
    +    if ! ftp -4 -o - https://$master/index.txt | grep -q "Welcome to $master"; then
    +        echo "https://$master/index.txt IPv4 health check failed"
    +        health_ok=0
    +    elif ! ftp -6 -o - https://$master/index.txt | grep -q "Welcome to $master"; then
    +        echo "https://$master/index.txt IPv6 health check failed"
    +        health_ok=0
    +    fi
    +    if [ $health_ok -eq 0 ]; then
    +        local tmp=$master
    +        master=$standby
    +        standby=$tmp
    +    fi
     
    -    .
    -    .
    -    .
    -}
    +    .
    +    .
    +    .
    +}
     

    The failover scripts looks for the ; Enable failover string in the DNS zone files and swaps the A and AAAA records of the DNS entries accordingly:
    @@ -7007,42 +7007,42 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    fishfinger$ grep failover /var/nsd/zones/master/foo.zone.zone
    -        300 IN A 46.23.94.99 ; Enable failover
    -        300 IN AAAA 2a03:6000:6f67:624::99 ; Enable failover
    -www     300 IN A 46.23.94.99 ; Enable failover
    -www     300 IN AAAA 2a03:6000:6f67:624::99 ; Enable failover
    -standby  300 IN A 23.88.35.144 ; Enable failover
    -standby  300 IN AAAA 2a01:4f8:c17:20f1::42 ; Enable failover
    +
    fishfinger$ grep failover /var/nsd/zones/master/foo.zone.zone
    +        300 IN A 46.23.94.99 ; Enable failover
    +        300 IN AAAA 2a03:6000:6f67:624::99 ; Enable failover
    +www     300 IN A 46.23.94.99 ; Enable failover
    +www     300 IN AAAA 2a03:6000:6f67:624::99 ; Enable failover
    +standby  300 IN A 23.88.35.144 ; Enable failover
    +standby  300 IN AAAA 2a01:4f8:c17:20f1::42 ; Enable failover
     

    -
    transform () {
    -  sed -E '
    -	/IN A .*; Enable failover/ {
    -	    /^standby/! {
    -	        s/^(.*) 300 IN A (.*) ; (.*)/\1 300 IN A '$(cat /var/nsd/run/master_a)' ; \3/;
    -	    }
    -	    /^standby/ {
    -	        s/^(.*) 300 IN A (.*) ; (.*)/\1 300 IN A '$(cat /var/nsd/run/standby_a)' ; \3/;
    -	    }
    -	}
    -	/IN AAAA .*; Enable failover/ {
    -	    /^standby/! {
    -	        s/^(.*) 300 IN AAAA (.*) ; (.*)/\1 300 IN AAAA '$(cat /var/nsd/run/master_aaaa)' ; \3/;
    -	    }
    -	    /^standby/ {
    -	        s/^(.*) 300 IN AAAA (.*) ; (.*)/\1 300 IN AAAA '$(cat /var/nsd/run/standby_aaaa)' ; \3/;
    -	    }
    -	}
    -	/ ; serial/ {
    -	    s/^( +) ([0-9]+) .*; (.*)/\1 '$(date +%s)' ; \3/;
    -	}
    -  '
    -}
    +
    transform () {
    +  sed -E '
    +	/IN A .*; Enable failover/ {
    +	    /^standby/! {
    +	        s/^(.*) 300 IN A (.*) ; (.*)/\1 300 IN A '$(cat /var/nsd/run/master_a)' ; \3/;
    +	    }
    +	    /^standby/ {
    +	        s/^(.*) 300 IN A (.*) ; (.*)/\1 300 IN A '$(cat /var/nsd/run/standby_a)' ; \3/;
    +	    }
    +	}
    +	/IN AAAA .*; Enable failover/ {
    +	    /^standby/! {
    +	        s/^(.*) 300 IN AAAA (.*) ; (.*)/\1 300 IN AAAA '$(cat /var/nsd/run/master_aaaa)' ; \3/;
    +	    }
    +	    /^standby/ {
    +	        s/^(.*) 300 IN AAAA (.*) ; (.*)/\1 300 IN AAAA '$(cat /var/nsd/run/standby_aaaa)' ; \3/;
    +	    }
    +	}
    +	/ ; serial/ {
    +	    s/^( +) ([0-9]+) .*; (.*)/\1 '$(date +%s)' ; \3/;
    +	}
    +  '
    +}
     

    After the failover, the script reloads nsd and performs a sanity check to see if DNS still works. If not, a rollback will be performed:
    @@ -7051,48 +7051,48 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #! Race condition !#
    -   
    -if [ -f $zone_file.bak ]; then
    -    mv $zone_file.bak $zone_file
    -fi
    +
    #! Race condition !#
    +   
    +if [ -f $zone_file.bak ]; then
    +    mv $zone_file.bak $zone_file
    +fi
     
    -cat $zone_file | transform > $zone_file.new.tmp 
    +cat $zone_file | transform > $zone_file.new.tmp 
     
    -grep -v ' ; serial' $zone_file.new.tmp > $zone_file.new.noserial.tmp
    -grep -v ' ; serial' $zone_file > $zone_file.old.noserial.tmp
    +grep -v ' ; serial' $zone_file.new.tmp > $zone_file.new.noserial.tmp
    +grep -v ' ; serial' $zone_file > $zone_file.old.noserial.tmp
     
    -echo "Has zone $zone_file changed?"
    -if diff -u $zone_file.old.noserial.tmp $zone_file.new.noserial.tmp; then
    -    echo "The zone $zone_file hasn't changed"
    -    rm $zone_file.*.tmp
    -    return 0
    -fi
    +echo "Has zone $zone_file changed?"
    +if diff -u $zone_file.old.noserial.tmp $zone_file.new.noserial.tmp; then
    +    echo "The zone $zone_file hasn't changed"
    +    rm $zone_file.*.tmp
    +    return 0
    +fi
     
    -cp $zone_file $zone_file.bak
    -mv $zone_file.new.tmp $zone_file
    -rm $zone_file.*.tmp
    -echo "Reloading nsd"
    -nsd-control reload
    +cp $zone_file $zone_file.bak
    +mv $zone_file.new.tmp $zone_file
    +rm $zone_file.*.tmp
    +echo "Reloading nsd"
    +nsd-control reload
     
    -if ! zone_is_ok $zone; then
    -    echo "Rolling back $zone_file changes"
    -    cp $zone_file $zone_file.invalid
    -    mv $zone_file.bak $zone_file
    -    echo "Reloading nsd"
    -    nsd-control reload
    -    zone_is_ok $zone
    -    return 3
    -fi
    +if ! zone_is_ok $zone; then
    +    echo "Rolling back $zone_file changes"
    +    cp $zone_file $zone_file.invalid
    +    mv $zone_file.bak $zone_file
    +    echo "Reloading nsd"
    +    nsd-control reload
    +    zone_is_ok $zone
    +    return 3
    +fi
     
    -for cleanup in invalid bak; do
    -    if [ -f $zone_file.$cleanup ]; then
    -        rm $zone_file.$cleanup
    -    fi
    -done
    +for cleanup in invalid bak; do
    +    if [ -f $zone_file.$cleanup ]; then
    +        rm $zone_file.$cleanup
    +    fi
    +done
     
    -echo "Failover of zone $zone to $MASTER completed"
    -return 1
    +echo "Failover of zone $zone to $MASTER completed"
    +return 1
     

    A non-zero return code (here, 3 when a rollback and 1 when a DNS failover was performed) will cause CRON to send an E-Mail with the whole script output.
    @@ -7149,13 +7149,13 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    # Weekly auto-failover for Let's Encrypt automation
    -local -i -r week_of_the_year=$(date +%U)
    -if [ $(( week_of_the_year % 2 )) -eq 0 ]; then
    -    local tmp=$master
    -    master=$standby
    -    standby=$tmp
    -fi
    +
    # Weekly auto-failover for Let's Encrypt automation
    +local -i -r week_of_the_year=$(date +%U)
    +if [ $(( week_of_the_year % 2 )) -eq 0 ]; then
    +    local tmp=$master
    +    master=$standby
    +    standby=$tmp
    +fi
     

    This way, a DNS failover is performed weekly so that the ACME automation can update the Let's Encrypt certificates (for master and standby) before they expire on each VM.
    @@ -7534,8 +7534,8 @@ SSFISHKISSFISHKISSFISHKISSFISHKIS SFIS by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    $ doas installboot sd0 # Update the bootloader (not for every upgrade required)
    -$ doas sysupgrade # Update all binaries (including Kernel)
    +
    $ doas installboot sd0 # Update the bootloader (not for every upgrade required)
    +$ doas sysupgrade # Update all binaries (including Kernel)
     

    sysupgrade downloaded and upgraded to the next release and rebooted the system. After the reboot, I run:
    @@ -7544,9 +7544,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    $ doas sysmerge # Update system configuration files
    -$ doas pkg_add -u # Update all packages
    -$ doas reboot # Just in case, reboot one more time
    +
    $ doas sysmerge # Update system configuration files
    +$ doas pkg_add -u # Update all packages
    +$ doas reboot # Just in case, reboot one more time
     

    That's it! Took me around 5 minutes in total! No issues, only these few comands, only 5 minutes! It just works! No problems, no conflicts, no tons (actually none) config file merge conflicts.
    @@ -7715,24 +7715,24 @@ jgs^^^^^^^`^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -log () {
    -    local -r level="$1"; shift
    -    local -r message="$1"; shift
    -    local -i pid="$$"
    +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)
    +    local -r callee=${FUNCNAME[1]}
    +    local -r stamp=$(date +%Y%m%d-%H%M%S)
     
    -    echo "$level|$stamp|$pid|$callee|$message" >&2
    -}
    +    echo "$level|$stamp|$pid|$callee|$message" >&2
    +}
     
    -at_home_friday_evening () {
    -    log INFO 'One Peperoni Pizza, please'
    -}
    +at_home_friday_evening () {
    +    log INFO 'One Peperoni Pizza, please'
    +}
     
    -at_home_friday_evening
    +at_home_friday_evening
     

    The output is as follows:
    @@ -7741,8 +7741,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ./logexample.sh
    -INFO|20231210-082732|123002|at_home_friday_evening|One Peperoni Pizza, please
    +
    ./logexample.sh
    +INFO|20231210-082732|123002|at_home_friday_evening|One Peperoni Pizza, please
     

    :(){ :|:& };:


    @@ -7776,18 +7776,18 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -outer() {
    -  inner() {
    -    echo 'Intel inside!'
    -  }
    -  inner
    -}
    +outer() {
    +  inner() {
    +    echo 'Intel inside!'
    +  }
    +  inner
    +}
     
    -inner
    -outer
    -inner
    +inner
    +outer
    +inner
     

    And let's execute it:
    @@ -7805,26 +7805,26 @@ Intel inside! by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -outer1() {
    -  inner() {
    -    echo 'Intel inside!'
    -  }
    -  inner
    -}
    +outer1() {
    +  inner() {
    +    echo 'Intel inside!'
    +  }
    +  inner
    +}
     
    -outer2() {
    -  inner() {
    -    echo 'Wintel inside!'
    -  }
    -  inner
    -}
    +outer2() {
    +  inner() {
    +    echo 'Wintel inside!'
    +  }
    +  inner
    +}
     
    -outer1
    -inner
    -outer2
    -inner
    +outer1
    +inner
    +outer2
    +inner
     

    And let's run it:
    @@ -7845,14 +7845,14 @@ Wintel inside! by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -some_expensive_operations() {
    -  echo "Doing expensive operations with '$1' from pid $$"
    -}
    +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 "{}"'
    +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:
    @@ -7877,15 +7877,15 @@ bash: line 1: some_expensive_operations: command not found by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -some_expensive_operations() {
    -  echo "Doing expensive operations with '$1' from pid $$"
    -}
    -export -f some_expensive_operations
    +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 "{}"'
    +for i in {0..9}; do echo $i; done \
    +  | xargs -P10 -I{} bash -c 'some_expensive_operations "{}"'
     

    When we run this now, we get:
    @@ -7910,19 +7910,19 @@ Doing expensive operations with '9' from pid 132840 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -some_other_function() {
    -  echo "$1"
    -}
    +some_other_function() {
    +  echo "$1"
    +}
     
    -some_expensive_operations() {
    -  some_other_function "Doing expensive operations with '$1' from pid $$"
    -}
    -export -f some_expensive_operations
    +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 "{}"'
    +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!
    @@ -7935,22 +7935,22 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -foo() {
    -  local foo=bar # Declare local/dynamic variable
    -  bar
    -  echo "$foo"
    -}
    +foo() {
    +  local foo=bar # Declare local/dynamic variable
    +  bar
    +  echo "$foo"
    +}
     
    -bar() {
    -  echo "$foo"
    -  foo=baz
    -}
    +bar() {
    +  echo "$foo"
    +  foo=baz
    +}
     
    -foo=foo # Declare global variable
    -foo # Call function foo
    -echo "$foo"
    +foo=foo # Declare global variable
    +foo # Call function foo
    +echo "$foo"
     

    Let's pause a minute. What do you think the output would be?
    @@ -7975,34 +7975,34 @@ foo by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -declare -r foo=foo
    -declare -r bar=bar
    +declare -r foo=foo
    +declare -r bar=bar
     
    -if [ "$foo" = foo ]; then
    -  if [ "$bar" = bar ]; then
    -    echo ok1
    -  fi
    -fi
    +if [ "$foo" = foo ]; then
    +  if [ "$bar" = bar ]; then
    +    echo ok1
    +  fi
    +fi
     
    -if [ "$foo" = foo ] && [ "$bar" == bar ]; then
    -  echo ok2a
    -fi
    +if [ "$foo" = foo ] && [ "$bar" == bar ]; then
    +  echo ok2a
    +fi
     
    -[ "$foo" = foo ] && [ "$bar" == bar ] && echo ok2b
    +[ "$foo" = foo ] && [ "$bar" == bar ] && echo ok2b
     
    -if [[ "$foo" = foo && "$bar" == bar ]]; then
    -  echo ok3a
    -fi
    +if [[ "$foo" = foo && "$bar" == bar ]]; then
    +  echo ok3a
    +fi
     
    - [[ "$foo" = foo && "$bar" == bar ]] && echo ok3b
    + [[ "$foo" = foo && "$bar" == bar ]] && echo ok3b
     
    -if test "$foo" = foo && test "$bar" = bar; then
    -  echo ok4a
    -fi
    +if test "$foo" = foo && test "$bar" = bar; then
    +  echo ok4a
    +fi
     
    -test "$foo" = foo && test "$bar" = bar && echo ok4b
    +test "$foo" = foo && test "$bar" = bar && echo ok4b
     

    The output we get is:
    @@ -8026,18 +8026,18 @@ ok4b by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -# Single line comment
    +# Single line comment
     
    -# These are two single line
    -# comments one after another
    +# These are two single line
    +# comments one after another
     
    -: <<COMMENT
    -This is another way a
    -multi line comment
    -could be written!
    -COMMENT
    +: <<COMMENT
    +This is another way a
    +multi line comment
    +could be written!
    +COMMENT
     

    I will not demonstrate the execution of this script, as it won't print anything! It's obviously not the most pretty way of commenting on your code, but it could sometimes be handy!
    @@ -8050,11 +8050,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    #!/usr/bin/env bash
    +
    #!/usr/bin/env bash
     
    -echo foo
    -echo echo baz >> $0
    -echo bar
    +echo foo
    +echo echo baz >> $0
    +echo bar
     

    When it is run, it will do:
    @@ -8432,42 +8432,42 @@ photoalbum makemake by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % photoalbum makemake
    -You may now customize ./photoalbumrc and run make
    +
    % photoalbum makemake
    +You may now customize ./photoalbumrc and run make
     
    -% cat Makefile
    -all:
    -	photoalbum generate photoalbumrc
    -clean:
    -	photoalbum clean photoalbumrc
    +% cat Makefile
    +all:
    +	photoalbum generate photoalbumrc
    +clean:
    +	photoalbum clean photoalbumrc
     
    -% cat photoalbumrc
    -# The title of the photoalbum
    -TITLE='A simple Photoalbum'
    +% cat photoalbumrc
    +# The title of the photoalbum
    +TITLE='A simple Photoalbum'
     
    -# Thumbnail height geometry
    -THUMBHEIGHT=300
    -# Normal geometry height (when viewing photo). Uncomment, to keep original size.
    -HEIGHT=1200
    -# Max previews per page.
    -MAXPREVIEWS=40
    -# Randomly shuffle all previews.
    -# SHUFFLE=yes
    +# Thumbnail height geometry
    +THUMBHEIGHT=300
    +# Normal geometry height (when viewing photo). Uncomment, to keep original size.
    +HEIGHT=1200
    +# Max previews per page.
    +MAXPREVIEWS=40
    +# Randomly shuffle all previews.
    +# SHUFFLE=yes
     
    -# Diverse directories, need to be full paths, not relative!
    -INCOMING_DIR=$(pwd)/incoming
    -DIST_DIR=$(pwd)/dist
    -TEMPLATE_DIR=/usr/share/photoalbum/templates/default
    -#TEMPLATE_DIR=/usr/share/photoalbum/templates/minimal
    +# Diverse directories, need to be full paths, not relative!
    +INCOMING_DIR=$(pwd)/incoming
    +DIST_DIR=$(pwd)/dist
    +TEMPLATE_DIR=/usr/share/photoalbum/templates/default
    +#TEMPLATE_DIR=/usr/share/photoalbum/templates/minimal
     
    -# Includes a .tar of the incoming dir in the dist, can be yes or no
    -TARBALL_INCLUDE=yes
    -TARBALL_SUFFIX=.tar
    -TAR_OPTS='-c'
    +# Includes a .tar of the incoming dir in the dist, can be yes or no
    +TARBALL_INCLUDE=yes
    +TARBALL_SUFFIX=.tar
    +TAR_OPTS='-c'
     
    -# Some debugging options
    -#set -e
    -#set -x
    +# Some debugging options
    +#set -e
    +#set -x
     

    In the case for irregular.ninja, I changed the defaults to the following:
    @@ -8476,38 +8476,38 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    --- photoalbumrc        2023-10-29 21:42:00.894202045 +0200
    -+++ photoalbumrc.new 2023-06-04 10:40:08.030994440 +0300
    -@@ -1,23 +1,24 @@
    - # The title of the photoalbum
    --TITLE='A simple Photoalbum'
    -+TITLE='Irregular.Ninja'
    +
    --- photoalbumrc        2023-10-29 21:42:00.894202045 +0200
    ++++ photoalbumrc.new 2023-06-04 10:40:08.030994440 +0300
    +@@ -1,23 +1,24 @@
    + # The title of the photoalbum
    +-TITLE='A simple Photoalbum'
    ++TITLE='Irregular.Ninja'
     
    - # Thumbnail height geometry
    --THUMBHEIGHT=300
    -+THUMBHEIGHT=400
    - # Normal geometry height (when viewing photo). Uncomment, to keep original size.
    --HEIGHT=1200
    -+HEIGHT=1800
    - # Max previews per page.
    - MAXPREVIEWS=40
    --# Randomly shuffle all previews.
    --# SHUFFLE=yes
    -+# Randomly shuffle
    -+SHUFFLE=yes
    + # Thumbnail height geometry
    +-THUMBHEIGHT=300
    ++THUMBHEIGHT=400
    + # Normal geometry height (when viewing photo). Uncomment, to keep original size.
    +-HEIGHT=1200
    ++HEIGHT=1800
    + # Max previews per page.
    + MAXPREVIEWS=40
    +-# Randomly shuffle all previews.
    +-# SHUFFLE=yes
    ++# Randomly shuffle
    ++SHUFFLE=yes
     
    - # Diverse directories, need to be full paths, not relative!
    --INCOMING_DIR=$(pwd)/incoming
    -+INCOMING_DIR=~/Nextcloud/Photos/irregular.ninja
    - DIST_DIR=$(pwd)/dist
    - TEMPLATE_DIR=/usr/share/photoalbum/templates/default
    - #TEMPLATE_DIR=/usr/share/photoalbum/templates/minimal
    + # Diverse directories, need to be full paths, not relative!
    +-INCOMING_DIR=$(pwd)/incoming
    ++INCOMING_DIR=~/Nextcloud/Photos/irregular.ninja
    + DIST_DIR=$(pwd)/dist
    + TEMPLATE_DIR=/usr/share/photoalbum/templates/default
    + #TEMPLATE_DIR=/usr/share/photoalbum/templates/minimal
     
    - # Includes a .tar of the incoming dir in the dist, can be yes or no
    --TARBALL_INCLUDE=yes
    -+TARBALL_INCLUDE=no
    - TARBALL_SUFFIX=.tar
    - TAR_OPTS='-c'
    + # Includes a .tar of the incoming dir in the dist, can be yes or no
    +-TARBALL_INCLUDE=yes
    ++TARBALL_INCLUDE=no
    + TARBALL_SUFFIX=.tar
    + TAR_OPTS='-c'
     

    So I changed the album title, adjusted some image and thumbnail dimensions, and I want all images to be randomly shuffled every time the album is generated! I also have all my photos in my Nextcloud Photo directory and don't want to copy them to the local incoming directory. Also, a tarball containing the whole album as a download isn't provided.
    @@ -8680,7 +8680,7 @@ blurs html index.html photos thumbs by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt --grep INFO --files "/var/log/dserver/*.log"
    +
    % dtail --servers serverlist.txt --grep INFO --files "/var/log/dserver/*.log"
     

    Hint: you can also provide a comma separated server list, e.g.: servers server1.example.org,server2.example.org:PORT,...
    @@ -8693,7 +8693,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt --grep INFO "/var/log/dserver/*.log"
    +
    % dtail --servers serverlist.txt --grep INFO "/var/log/dserver/*.log"
     

    Aggregating logs


    @@ -8706,10 +8706,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt \
    -    --files '/var/log/dserver/*.log' \
    -    --query 'from STATS select sum($goroutines),sum($cgocalls),
    -             last($time),max(lifetimeConnections)'
    +
    % dtail --servers serverlist.txt \
    +    --files '/var/log/dserver/*.log' \
    +    --query 'from STATS select sum($goroutines),sum($cgocalls),
    +             last($time),max(lifetimeConnections)'
     

    Beware: For map-reduce queries to work, you have to ensure that DTail supports your log format. Check out the documentaiton of the DTail query language and the DTail log formats on the DTail homepage for more information.
    @@ -8722,10 +8722,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt \
    -    --files '/var/log/dserver/*.log' \
    -    'from STATS select sum($goroutines),sum($cgocalls),
    -     last($time),max(lifetimeConnections)'
    +
    % dtail --servers serverlist.txt \
    +    --files '/var/log/dserver/*.log' \
    +    'from STATS select sum($goroutines),sum($cgocalls),
    +     last($time),max(lifetimeConnections)'
     

    Here is another example:
    @@ -8734,10 +8734,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt \
    -    --files '/var/log/dserver/*.log' \
    -    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    -             lifetimeConnections group by $hostname order by max($cgocalls)'
    +
    % dtail --servers serverlist.txt \
    +    --files '/var/log/dserver/*.log' \
    +    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    +             lifetimeConnections group by $hostname order by max($cgocalls)'
     

    Tail map-reduce example 2
    @@ -8748,9 +8748,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail --servers serverlist.txt \
    -    --files '/var/log/dserver/*.log' \
    -    --query 'from STATS select ... outfile append result.csv'
    +
    % dtail --servers serverlist.txt \
    +    --files '/var/log/dserver/*.log' \
    +    --query 'from STATS select ... outfile append result.csv'
     

    How to use dcat


    @@ -8763,7 +8763,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dcat --servers serverlist.txt --files /etc/hostname
    +
    % dcat --servers serverlist.txt --files /etc/hostname
     

    Cat example
    @@ -8774,7 +8774,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dcat --servers serverlist.txt /etc/hostname
    +
    % dcat --servers serverlist.txt /etc/hostname
     

    How to use dgrep


    @@ -8785,9 +8785,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dgrep --servers server1.example.org:2223 \
    -    --files /etc/passwd \
    -    --regex nologin
    +
    % dgrep --servers server1.example.org:2223 \
    +    --files /etc/passwd \
    +    --regex nologin
     

    Generally, dgrep is also a very useful way to search historic application logs for certain content.
    @@ -8804,10 +8804,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dmap --servers serverlist.txt \
    -    --files '/var/log/dserver/*.log' \
    -    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    -             lifetimeConnections group by $hostname order by max($cgocalls)'
    +
    % dmap --servers serverlist.txt \
    +    --files '/var/log/dserver/*.log' \
    +    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    +             lifetimeConnections group by $hostname order by max($cgocalls)'
     

    Remember: For that to work, you have to make sure that DTail supports your log format. You can either use the ones already defined in internal/mapr/logformat or add an extension to support a custom log format. The example here works out of the box though, as DTail understands its own log format already.
    @@ -8830,9 +8830,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dmap --files /var/log/dserver/dserver.log
    -    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    -              lifetimeConnections group by $hostname order by max($cgocalls)'
    +
    % dmap --files /var/log/dserver/dserver.log
    +    --query 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    +              lifetimeConnections group by $hostname order by max($cgocalls)'
     

    As a shorthand version the following command can be used:
    @@ -8841,9 +8841,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dmap 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    -        lifetimeConnections group by $hostname order by max($cgocalls)' \
    -        /var/log/dsever/dserver.log
    +
    % dmap 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    +        lifetimeConnections group by $hostname order by max($cgocalls)' \
    +        /var/log/dsever/dserver.log
     

    You can also use a file input pipe as follows:
    @@ -8852,9 +8852,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % cat /var/log/dserver/dserver.log | \
    -    dmap 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    -          lifetimeConnections group by $hostname order by max($cgocalls)'
    +
    % cat /var/log/dserver/dserver.log | \
    +    dmap 'from STATS select $hostname,max($goroutines),max($cgocalls),$loadavg,
    +          lifetimeConnections group by $hostname order by max($cgocalls)'
     

    Aggregating CSV files


    @@ -8865,16 +8865,16 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % cat example.csv
    -name,lastname,age,profession
    -Michael,Jordan,40,Basketball player
    -Michael,Jackson,100,Singer
    -Albert,Einstein,200,Physician
    -% dmap --query 'select lastname,name where age > 40 logformat csv outfile result.csv' example.csv
    -% cat result.csv
    -lastname,name
    -Jackson,Michael
    -Einstein,Albert
    +
    % cat example.csv
    +name,lastname,age,profession
    +Michael,Jordan,40,Basketball player
    +Michael,Jackson,100,Singer
    +Albert,Einstein,200,Physician
    +% dmap --query 'select lastname,name where age > 40 logformat csv outfile result.csv' example.csv
    +% cat result.csv
    +lastname,name
    +Jackson,Michael
    +Einstein,Albert
     

    DMap can also be used to query and aggregate CSV files from remote servers.
    @@ -8887,44 +8887,44 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    % dtail /var/log/dserver/dserver.log
    +
    % dtail /var/log/dserver/dserver.log
     

    -
    % dtail --logLevel trace /var/log/dserver/dserver.log
    +
    % dtail --logLevel trace /var/log/dserver/dserver.log
     

    -
    % dcat /etc/passwd
    +
    % dcat /etc/passwd
     

    -
    % dcat --plain /etc/passwd > /etc/test
    -# Should show no differences.
    -diff /etc/test /etc/passwd 
    +
    % dcat --plain /etc/passwd > /etc/test
    +# Should show no differences.
    +diff /etc/test /etc/passwd 
     

    -
    % dgrep --regex ERROR --files /var/log/dserver/dsever.log
    +
    % dgrep --regex ERROR --files /var/log/dserver/dsever.log
     

    -
    % dgrep --before 10 --after 10 --max 10 --grep ERROR /var/log/dserver/dsever.log
    +
    % dgrep --before 10 --after 10 --max 10 --grep ERROR /var/log/dserver/dsever.log
     

    Use --help for more available options. Or go to the DTail page for more information! Hope you find DTail useful!
    @@ -9094,9 +9094,9 @@ DC on fire: by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    if [ -n "$foo" ]; then
    -  echo "$foo"
    -fi
    +
    if [ -n "$foo" ]; then
    +  echo "$foo"
    +fi
     

    Please run source-highlight --lang-list for a list of all supported languages.
    @@ -9125,7 +9125,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    declare -xr MASTODON_URI='https://fosstodon.org/@snonux'
    +
    declare -xr MASTODON_URI='https://fosstodon.org/@snonux'
     

    and add the following into your index.gmi:
    @@ -9140,7 +9140,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    <a href='https://fosstodon.org/@snonux' rel='me'>Me at Mastodon</a>
    +
    <a href='https://fosstodon.org/@snonux' rel='me'>Me at Mastodon</a>
     

    More


    @@ -9642,11 +9642,11 @@ Have a nice day! by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    git clone https://codeberg.org/snonux/gogios.git
    -cd gogios
    -go build -o gogios cmd/gogios/main.go
    -doas cp gogios /usr/local/bin/gogios
    -doas chmod 755 /usr/local/bin/gogios
    +
    git clone https://codeberg.org/snonux/gogios.git
    +cd gogios
    +go build -o gogios cmd/gogios/main.go
    +doas cp gogios /usr/local/bin/gogios
    +doas chmod 755 /usr/local/bin/gogios
     

    You can use cross-compilation if you want to compile Gogios for OpenBSD on a Linux system without installing the Go compiler on OpenBSD. Follow these steps:
    @@ -9655,9 +9655,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    export GOOS=openbsd
    -export GOARCH=amd64
    -go build -o gogios cmd/gogios/main.go
    +
    export GOOS=openbsd
    +export GOARCH=amd64
    +go build -o gogios cmd/gogios/main.go
     

    On your OpenBSD system, copy the binary to /usr/local/bin/gogios and set the correct permissions as described in the previous section. All steps described here you could automate with your configuration management system of choice. I use Rexify, the friendly configuration management system, to automate the installation, but that is out of the scope of this document.
    @@ -9672,11 +9672,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    doas adduser -group _gogios -batch _gogios
    -doas usermod -d /var/run/gogios _gogios
    -doas mkdir -p /var/run/gogios
    -doas chown _gogios:_gogios /var/run/gogios
    -doas chmod 750 /var/run/gogios
    +
    doas adduser -group _gogios -batch _gogios
    +doas usermod -d /var/run/gogios _gogios
    +doas mkdir -p /var/run/gogios
    +doas chown _gogios:_gogios /var/run/gogios
    +doas chmod 750 /var/run/gogios
     

    Please note that creating a user and group might differ depending on your operating system. For other operating systems, consult their documentation for creating system users and groups.
    @@ -9689,8 +9689,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    doas pkg_add monitoring-plugins
    -doas pkg_add nrpe # If you want to execute checks remotely via NRPE.
    +
    doas pkg_add monitoring-plugins
    +doas pkg_add nrpe # If you want to execute checks remotely via NRPE.
     

    Once the installation is complete, you can find the monitoring plugins in the /usr/local/libexec/nagios directory, which then can be configured to be used in gogios.json.
    @@ -9717,41 +9717,41 @@ echo 'This is a test email from OpenBSD.' | mail -s 'Test Email' by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    {
    -  "EmailTo": "paul@dev.buetow.org",
    -  "EmailFrom": "gogios@buetow.org",
    -  "CheckTimeoutS": 10,
    -  "CheckConcurrency": 2,
    -  "StateDir": "/var/run/gogios",
    -  "Checks": {
    -    "Check ICMP4 www.foo.zone": {
    -      "Plugin": "/usr/local/libexec/nagios/check_ping",
    -      "Args": [ "-H", "www.foo.zone", "-4", "-w", "50,10%", "-c", "100,15%" ],
    -      "Retries": 3,
    -      "RetryInterval": 10
    -    },
    -    "Check ICMP6 www.foo.zone": {
    -      "Plugin": "/usr/local/libexec/nagios/check_ping",
    -      "Args": [ "-H", "www.foo.zone", "-6", "-w", "50,10%", "-c", "100,15%" ],
    -      "Retries": 3,
    -      "RetryInterval": 10
    -    },
    -    "www.foo.zone HTTP IPv4": {
    -      "Plugin": "/usr/local/libexec/nagios/check_http",
    -      "Args": ["www.foo.zone", "-4"],
    -      "DependsOn": ["Check ICMP4 www.foo.zone"]
    -    },
    -    "www.foo.zone HTTP IPv6": {
    -      "Plugin": "/usr/local/libexec/nagios/check_http",
    -      "Args": ["www.foo.zone", "-6"],
    -      "DependsOn": ["Check ICMP6 www.foo.zone"]
    -    }
    -    "Check NRPE Disk Usage foo.zone": {
    -      "Plugin": "/usr/local/libexec/nagios/check_nrpe",
    -      "Args": ["-H", "foo.zone", "-c", "check_disk", "-p", "5666", "-4"]
    -    }
    -  }
    -}
    +
    {
    +  "EmailTo": "paul@dev.buetow.org",
    +  "EmailFrom": "gogios@buetow.org",
    +  "CheckTimeoutS": 10,
    +  "CheckConcurrency": 2,
    +  "StateDir": "/var/run/gogios",
    +  "Checks": {
    +    "Check ICMP4 www.foo.zone": {
    +      "Plugin": "/usr/local/libexec/nagios/check_ping",
    +      "Args": [ "-H", "www.foo.zone", "-4", "-w", "50,10%", "-c", "100,15%" ],
    +      "Retries": 3,
    +      "RetryInterval": 10
    +    },
    +    "Check ICMP6 www.foo.zone": {
    +      "Plugin": "/usr/local/libexec/nagios/check_ping",
    +      "Args": [ "-H", "www.foo.zone", "-6", "-w", "50,10%", "-c", "100,15%" ],
    +      "Retries": 3,
    +      "RetryInterval": 10
    +    },
    +    "www.foo.zone HTTP IPv4": {
    +      "Plugin": "/usr/local/libexec/nagios/check_http",
    +      "Args": ["www.foo.zone", "-4"],
    +      "DependsOn": ["Check ICMP4 www.foo.zone"]
    +    },
    +    "www.foo.zone HTTP IPv6": {
    +      "Plugin": "/usr/local/libexec/nagios/check_http",
    +      "Args": ["www.foo.zone", "-6"],
    +      "DependsOn": ["Check ICMP6 www.foo.zone"]
    +    }
    +    "Check NRPE Disk Usage foo.zone": {
    +      "Plugin": "/usr/local/libexec/nagios/check_nrpe",
    +      "Args": ["-H", "foo.zone", "-c", "check_disk", "-p", "5666", "-4"]
    +    }
    +  }
    +}
     

      @@ -9780,7 +9780,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
      doas -u _gogios /usr/local/bin/gogios -cfg /etc/gogios.json
      +
      doas -u _gogios /usr/local/bin/gogios -cfg /etc/gogios.json
       

      To run Gogios via CRON on OpenBSD as the gogios user and check all services once per minute, follow these steps:
      @@ -10032,7 +10032,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
      $ raku guprecords.raku --stats=dir=$HOME/git/uprecords/stats --all
      +
      $ raku guprecords.raku --stats=dir=$HOME/git/uprecords/stats --all
       

      This command will generate a comprehensive uptime report from the collected statistics, making it easy to review and enjoy the data.
      @@ -10446,8 +10446,8 @@ Blablabla... by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
      declare -xr PRE_GENERATE_HOOK=./pre_generate_hook.sh
      -declare -xr POST_PUBLISH_HOOK=./post_publish_hook.sh
      +
      declare -xr PRE_GENERATE_HOOK=./pre_generate_hook.sh
      +declare -xr POST_PUBLISH_HOOK=./post_publish_hook.sh
       

      Use of safer Bash options


      @@ -10464,10 +10464,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
      % cat gemfeed/2023-02-26-title-here.gmi
      -# Title here
      +
      % cat gemfeed/2023-02-26-title-here.gmi
      +# Title here
       
      -The remaining content of the Gemtext file...
      +The remaining content of the Gemtext file...
       

      Gemtexter will add a line starting with > Published at ... now. Any subsequent Atom feed generation will then use that date.
      @@ -10476,12 +10476,12 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
      % cat gemfeed/2023-02-26-title-here.gmi
      -# Title here
      +
      % cat gemfeed/2023-02-26-title-here.gmi
      +# Title here
       
      -> Published at 2023-02-26T21:43:51+01:00
      +> Published at 2023-02-26T21:43:51+01:00
       
      -The remaining content of the Gemtext file...
      +The remaining content of the Gemtext file...
       

      XMLLint support


      -- cgit v1.2.3