Autodocumenting bash script using perldoc

I may know how to code in C/C++/C#/VHDL/bash/python/Perl my prefered language will always be the one that takes the less line for the job, and I will have no SHAME mixing them.

-- Doctor Frankenstein
I would rate myself as a python coder, but sometimes, I don't care which language I « prefer », there is a task and there are languages easier to use for one tasks.

Here, on my last toy project originating from a poc I chose bash because when it comes to spawning processes, sending and catching signals (python is way unreliable when it come to signal delivery (note to myself link to my post experminenting on this topic)), bash is better and above all « way more concise ». I don't want to fiddle with subprocess.popen.PIPE when I can add a & at the end or using « $() ». Also the ${VAL:-default_val} is really concise when it comes with dealing with variable passed by environment.

But, something DOES not exists in bash that exists in python : self documentation thanks to docstring and SPHINX.

And I love documentation.

So the other day, I was butchering the munin plugins to make them fit in my solution when I noticed this weired pattern :
#!/bin/sh
# -*- sh -*-

: << =cut

=head1 NAME

interrupts - list number of interrupts since boot (linux) or the interrupt rate per interrupt

=head1 CONFIGURATION

=cut
As a former Perl coder, I recognized both a perl HEREDOC and a shell HEREDOC. A way of partially doing a polyglot code. A plolyglot is valid code for two languages like this one in python+Perl
q = 0 or """ #=;$A=41;sub A { ~-$A+2};  A() && q' """
A=lambda A: -~A  #';
print( A(41) ) # python + perl = <3
So you can do : perldoc ./bash_with_here_doc_called_=cut.sh and it will yield a doc because someone found a way to transform a shell script in a valid enough Perl with heredoc. What a trick.

I am not fond of the perldoc markup syntax that is a tad too verbose for me, but I really appreciate the redactionnal advices given by the Perl community. And, when you code, the markup language is readable enough that it acts as a good comment on the API.
I may have left my occupation as a paid Perl developer, it still has a lot of community related trumps and practices I do appreciate. So the deal is done, I will live with pod verbosity in exchange for clear docs.

Soo without further ado here is how I document a script with the script itself :
#!/usr/bin/env bash
<< '=cut'
=head1 NAME

start.sh

=head2 DESCRIPTION

Launches the networked apparatus of measures. It is the reciprocal function
of stop.sh

=head2 SYNOPSIS

All arguments are passed by environment variables

    [TICK=2] [LURKER=] [BROADCAST=192.168.1.255] [RANGE=24] [SINCE=900] start.sh

=head2 OPTIONS

=over

=item TICK

TICK is the initial clock given to the system. It will however converge
to its computed value.

=item LURKER

When LURKER is set, the data collecting agent is launched and process 
all probes sent on the given broadcast address

=item BROADCAST

UDP BROADCAST address to use

=item RANGE

Range in the form [0-32] to specify the BROADCAST range. 

Ex: 24 will specify $BROADCAST/24

=item SINCE

Argument given to the html generator to know how much seconds since NOW must
be shown in the graph.

=back

=cut

LURKER=${LURKER:-}
cd $( dirname $0 )
HERE="."
SINCE=${SINCE:-900}
TICK=${TICK:-2}
BROADCAST=${BROADCAST:-"192.168.1.255"}
RANGE=24
export TICK
$HERE/stop.sh 
echo $$ > $HERE/pid/$( basename $0).pid
[ -e pid ]  || mkdir pid
[ -e log ]  || mkdir log
[ -e run ]  || mkdir run
[ -e data ] || mkdir data
if [ ! -z "$LURKER" ]; then
    SINCE=$SINCE DAEMON=1 $HERE/bin/mkhtml.sh &
    LURKER=$LURKER $HERE/bin/launch_lurker.sh &
fi
BROADCAST=$BROADCAST RANGE=$RANGE TICK=$TICK $HERE/bin/launch_writer.sh &
TICK=$TICK $HERE/bin/clock.sh &

which generates
$ perldoc -o text start.sh

NAME
    start.sh

  DESCRIPTION
    Launches the networked apparatus of measures. It is the reciprocal
    function of stop.sh

  SYNOPSIS
    All arguments are passed by environment variables

        [TICK=2] [LURKER=] [BROADCAST=192.168.1.255] [RANGE=24] [SINCE=900] start.sh

  OPTIONS
    TICK
        TICK is the initial clock given to the system. It will however
        converge to its computed value.

    LURKER
        When LURKER is set, the data collecting agent is launched and
        process all probes sent on the given broadcast address

    BROADCAST
        UDP BROADCAST address to use

    RANGE
        Range in the form [0-32] to specify the BROADCAST range.

        Ex: 24 will specify $BROADCAST/24

    SINCE
        Argument given to the html generator to know how much seconds since
        NOW must be shown in the graph.

Which also can help generates the man pages if required in the future.

So to generates AUTOMATICALLY all my docs and user my README.md (in markdown) I borrow the power of pandoc and bash :
#!/usr/bin/env bash
<< =cut

=head1 NAME

mkdoc.sh

=head2 SYNOPSIS

Generates the doc. Requires pandoc for markdown to html conversion

    ./mkdoc.sh

=cut

rm doc -rf
[ -d doc ] || mkdir -p doc/img
cp img/* doc/img/

for i in $( find . -name "*sh" ); do 
    DST="doc/$( dirname $i)"
    [ -d $DST ] || mkdir -p $DST
    pod2html --htmlroot=doc --htmldir=doc "$i" > "$DST/$(basename $i).html"
done
for i in $( find ./plugin -type f -not -path "./plugin/*enabled" ); do 
    DST="doc/$( dirname $i)"
    [ -d $DST ] || mkdir -p $DST
    pod2html "$i" > "$DST/$( basename $i).html"
done
RES=""
cd doc
pandoc ../README.md -o index.html
echo "<ul>" >> index.html

for i in $( find . -name "*html" -a -not -path ".*.git*" | sort ); do
    echo "<li><a href=$i > $(dirname $i)/$( basename $i .html )</a></li>" >> index.html ;
done
echo "</ul>" >> index.html
# and let's generate markdown and make them able to cross reference each others in both html and md
for i in $( find . -name "*html" -a -not -path ".*.git*" | sort ); do
    OUT="$(dirname $i)/$( basename $i .html ).md"
    pandoc $i -o "$OUT"
    perl -i -ane 's/\((.*).html\)/\($1.md\)/ and print $_ or print $_'  $OUT~
done

And it populates a doc dir with all the html.
At the end of the day, I have a bash framework that is self documented à la python sphinx with less overhead.

EDIT : it you can also document a python code with perldoc :

#!/usr/bin/env python3
"""<< =cut

=head1 NAME

launch_lurker.py

=head2 SYNOPSYS

[PORT=6666] ./launch_lurker

=head2 OPTIONS

see L<file:../start.sh.html> for explanation of the options
clock tick 37
=cut
"""
from socket import *
import os
...
Gives :
perldoc bin/launch_lurker.py 
clock tick 46
LAUNCH_LURKER.PY(1)   User Contributed Perl Documentation  LAUNCH_LURKER.PY(1)


NAME
       launch_lurker.py

   SYNOPSYS
       [HOST=0.0.0.0] [PORT=6666] ./launch_lurker

   OPTIONS
       see <file:../start.sh.html> for explanation of the options =back

perl v5.36.3                      2024-06-29               LAUNCH_LURKER.PY(1)
(END)

Plotting ASCII histogram with bash from time series

Imagine, you build a distributed system.

While the idiot look at the average, the tamed system engineer might want histograms.

An histogram often reveals more than meet the eyes, one of the most important stuff we look for is mulmtimodal.

When everything happens randomly in a distributed system metrics are gonna be spread with a law which according to the randomness at play will often results in a peak value and a spread in the histogram.

If you are interested in early detection of agents leaving the hurd or the impact of a modification on the metrics, non homonegeity in causality will spread in your histogram.

user story


I want to plot an ascii historam because I am on a server without Xserver/wayland coming from CSV in the form timestamp value. And I would like to use at much gnuplot-lite.
And I still havn't installed any other stuff than bash, so I would like to parse the file in bash :D

Solution



Well thanks to stackoverflow the gnuplot part is easy. The more annoying part is bash and it's unablity to deal with floats and the fact I read ratio of load usage (ranging from 0 to ... 4 since I have 4 cpus).

$ cat plot_histo.sh 
declare -a HISTO
SCALE=${2:-1}
TOTAL=0
LINE=0
X=${X:100}
Y=${Y:40}
while IFS= read p; do
    LINE=$(( LINE + 1 ))
    DATA=$( echo $p | cut -d " " -f2 )
    DATA=$( printf "%.0f" $( awk "BEGIN { print $DATA * $SCALE }" ) )
    TOTAL=$(( TOTAL + DATA ))
    HISTO[$DATA]=$(( ${HISTO[$DATA]} + 1 ))

done < $1 
for i in "${!HISTO[@]}"; do
    echo "$i ${HISTO[$i]}"
done > histo.data
echo  "total sample:$LINE"
echo -n "average value:"
awk "BEGIN { print $TOTAL/$LINE }"

gnuplot -e "set style histogram rowstacked gap 0 ;
set terminal dumb $X $Y ;
set xtics $SCALE;
bin(x,width)=width*floor(x/width);
plot \"histo.data\"  smooth freq with boxes ;"

Not very impressive :D Here it is with data ranging from 0 to n :
$ $X=100 Y=40 ./plot_histo.sh ./badazz%probe_received.csv 
total sample:1211
average value:13.3386

                                                                                                    
  500 +-----------------------------------------------------------------------------------------+   
      |    +   +    *******  +   +    +   +    +   +    +   +    +   +    +   +    +   +    +   |   
      |             *     *                                                "histo.data" ******* |   
      |             *     *                                                                     |   
  450 |-+           *     *                                                                   +-|   
      |             *     *                                                                     |   
      |             *     *                                                                     |   
  400 |-+           *     *                                                                   +-|   
      |             *     *                                                                     |   
      |             *     *                                                                     |   
      |             *     *                                                                     |   
  350 |-+           *     *                                                                   +-|   
      |             *     *                                                                     |   
      |             *     *                                                                     |   
  300 |-+           *     *                                                                   +-|   
      |             *     *                                                                     |   
      |             *     *                                                                     |   
      |             *     *                                                                     |   
  250 |-+           *     *                                                                   +-|   
      |             *     *                                                                     |   
      |             *     *                                                                     |   
      |             *     *                                                                     |   
  200 |-+           *     *                                                                   +-|   
      |             *     *                                                                     |   
      |             *     *                                        *****                        |   
  150 |-+           *     *                                        *   *    *****             +-|   
      |             *     *                                        *   *    *   *               |   
      |             *     *                                        *   *    *   ******          |   
      |             *     *                                        *   *    *   *    *          |   
  100 |-+           *     *                                        *   *    *   *    *        +-|   
      |             *     *                                        *   *    *   *    *          |   
      |             *     *                                        *   *    *   *    *          |   
   50 |-******      *     *                                   ******   ******   *    *   *******|   
      | *    *      *     *                                   *    *   *    *   *    *   *    * |   
      | *    *      *     *                                   *    *   *    *   *    *   *    * |   
      | *  + * +    *   + *  +   +    +   +    +   +    +   + *  + * + *  + * + *  + * + *  + * |   
    0 +-----------------------------------------------------------------------------------------+   
      3    4   5    6   7    8   9    10  11   12  13   14  15   16  17   18  19   20  21   22  23  
                                                                                                                                                                                                                
The bimodal comes from me launching a new series of probe on the experiment, and the initial data of probe received per campaign of measurement shows a bimodal where I have either ~7 easures per campaigns and almost no loss to 20 probes per campaing and more spread.

A useful tool :D

But bash don't like floats and well, CPU is all about floats, how does it behave ? Do we see a bimodal from launching a measure ?

$ ./plot_histo.sh ./badazz%load_15.csv 100
total sample:958
average value:118.201

                                                                                                    
  50 +------------------------------------------------------------------------------------------+   
     |                                             +         *                                  |   
     |                                                       *             "histo.data" ******* |   
     |                                     *                 *                                  |   
  45 |-+                                   *                 *                                +-|   
     |                                     *                 *                                  |   
     |                                     *                 *                                  |   
  40 |-+                                   *                 *                                +-|   
     |                                     *                **                                  |   
     |                                     *                **                                  |   
     |                                     *                **                                  |   
  35 |-+                                   *                **                                +-|   
     |                                     *                ***                                 |   
     |                                     *                ***                                 |   
  30 |-+                                 ***                ***                               +-|   
     |                                   ***                ***                                 |   
     |                                   ***                ***                                 |   
     |                                   ***                ***                                 |   
  25 |-+                                 ***                ***                               +-|   
     |                                   ***              *****                                 |   
     |                                   ***              *****     *                           |   
     |                                   ***              *****     *           **              |   
  20 |-+                                 ***              *****     *           **            +-|   
     |                               *   ***              *****     *          ***              |   
     |                               *   ****             *****    **          ***              |   
  15 |-+                             *   ****             ******   **          ***            +-|   
     |                               *   ****             ******   **          ***              |   
     |                           *   *   ****** **        ******   **        *****              |   
     |                           *   *   **** * **        ******** **        *****              |   
  10 |-+                         *   *   **** * **      ********** **        *****            +-|   
     |                           * ***   **** * **      ********** **  *  ** *****              |   
     |                           * ***   **** * ** **** ********** *** *  ** ******* **         |   
   5 |-+                        ****** ****** * ** * ******************** *************       +-|   
     |                          ****** ****** * ** * ******************** *************         |   
     |                          ************* ****** **********************************         |   
     |                          ************* * ** * **********************************         |   
   0 +------------------------------------------------------------------------------------------+   
     0                                            100                                          200  
By adding a scale factor of 100 I made all measures expressed as a ratio of 1 turn into a ratio of 100, hence creating bins of 1 percent of the ratio.

Hence by multiplying by 10 I make the bins of 1/10 th the size :D
$ ./plot_histo.sh ./badazz%load_15.csv 10 
total sample:963
average value:11.7985

                                                                                                    
  300 +-----------------------------------------------------------------------------------------+   
      |                                            +                                            |   
      |                                                                    "histo.data" ******* |   
      |                                                                                         |   
      |                                                                                         |   
      |                                                   *****                                 |   
  250 |-+                                                 *   *                               +-|   
      |                                                   *   *                                 |   
      |                                                   *   *                                 |   
      |                                                   *   *                                 |   
      |                                                   *   *                                 |   
      |                                 *****             *   *                                 |   
  200 |-+                               *   *             *   *                               +-|   
      |                                 *   *             *   *                                 |   
      |                                 *   *             *   *                                 |   
      |                                 *   *             *   *                                 |   
      |                                 *   *             *   *                                 |   
      |                                 *   *             *   *                                 |   
  150 |-+                               *   *             *   *                               +-|   
      |                                 *   *             *   *                                 |   
      |                                 *   *             *   *                                 |   
      |                                 *   *             *   *                                 |   
      |                                 *   *             *   *                                 |   
      |                                 *   *             *   *                                 |   
  100 |-+                               *   *             *   *    *****                      +-|   
      |                                 *   *             *   *    *   *                        |   
      |                                 *   *             *   *    *   *    *****               |   
      |                                 *   *             *   *    *   *    *   ******          |   
      |                                 *   *             *   *    *   *    *   *    *          |   
      |                                 *   *             *   *    *   *    *   *    *          |   
   50 |-+                          ******   *             *   ******   *    *   *    *        +-|   
      |                            *    *   *             *   *    *   *    *   *    *          |   
      |                        *****    *   *             *   *    *   ******   *    *          |   
      |                        *   *    *   *    **********   *    *   *    *   *    *****      |   
      |                        *   *    *   ******   *    *   *    *   *    *   *    *   *      |   
      |                        *   *    *   *    * + *    *   *    *   *    *   *    *   *      |   
    0 +-----------------------------------------------------------------------------------------+   
      0                                            10                                           20  
      
We do have a bimodal on a computer doing nothing but measurement. When scrutinizing a computer for data most people think for time serie data as the most important, but frequential data are also an important tool especially for non linear phenomenon : a change of number in the modal of a data indicates that somewhere on the system « something brought a perturbation ». It is basically useful for early detection of something going wrong or better and thus an important tool when making a time oriented measure.

The simplest (unsecure) monitoring system you can do in 41 lines of code

Any distributed system is fated to become a monitoring system of itself at first.
-- unknown


What are a monitoring system and a distributed system ?

One is a fault tolerant system which aims at being decentralized (it is pretty much a design esthetic), and the other one is a system to detect faults.

A fault tolerant system by nature having to deal with fault sometimes pro-actively requires to be able to monitor faults. Hence, a distributed system always begins its life with a trunk of monitoring on which you hook watchdogs that can help your system adapt.
Couldflare anti DOS infrastructure is basically one of this system both of monitoring and distributed fault tolerance.
I pretty much suspect nefltix infrastructure to have been designed around a monitoring system.

Anyway our task here is to design the fundation of a distributed system where we have probes and consumers that can live without caring of each others.

The probe

The probe will read the CPU load on both a linux and a freeBSD

linux probe

$cat probe.sh 
#!/usr/bin/env bash
for (( i ; i<3;i++)); do
    echo $( hostname ):load_$(( 5 * ( i + 1) )):$( cat /proc/loadavg | cut -d " " -f $(( i + 1 )) ):GAUGE
done
01:29:14 11616 jul@badazz:~/src/pubsub
$./probe.sh 
badazz:load_5:0.97:GAUGE
badazz:load_10:1.17:GAUGE
badazz:load_15:1.11:GAUGE
The probe has the following «:» delimited format :
  • the id of the probe
  • the name of the data source
  • its value
  • its intended type in a rrd usage

The freebsd probe

[user@freebsd-14 ~]$ cat probe.sh 
#!/usr/bin/env bash
for (( i=0 ; i<3;i++)); do
        echo $( hostname ):load_$(( 5 * ( i + 1) )):$( sysctl vm.loadavg | cut -d " " -f $(( i + 3 )) ):GAUGE
done
[user@freebsd-14 ~]$ ./probe.sh 
freebsd-14.0_RELEASE:load_5:0.79:GAUGE
freebsd-14.0_RELEASE:load_10:0.81:GAUGE
freebsd-14.0_RELEASE:load_15:0.83:GAUGE

The monitor

The monitor takes the output of the probe and consume it. Here we make a simple data dumper of the input into there destinations (csv files and rrd).
#!/usr/bin/env bash
echo "$$" > mastermind.pid
trap "echo ping" SIGUSR1
function create_rrd() {
while read p; do
    local SOURCE=$1
    local DS=$2
    local DST=$3
    rrdtool create "$SOURCE.$DS.rrd"   \
    --step 1 \
    DS:x:$DST:1:0:99 \
   RRA:AVERAGE:0.5:1:864000 \
   RRA:AVERAGE:0.5:60:129600 \
   RRA:AVERAGE:0.5:3600:13392 \
   RRA:AVERAGE:0.5:86400:3660
}
while read p; do
    SOURCE= "$( echo $p | cut -d':' -f1 )"
    DS=     "$( echo $p | cut -d':' -f2 )"
    VALUE=  "$( echo $p | cut -d':' -f3 )"
    DST=    "$( echo $p | cut -d':' -f4 )"
    OFB="${SOURCE}.${DS}"
    [ -e "$OFB.rrd" ] || create_rrd $SOURCE $DS $DST
    NOW="$( date +'%s' )"
    # rrd insert
    rrdtool update "$OFB.rrd" $NOW:${VALUE}
    # csv insert
    echo $NOW $VALUE >> $OFB.csv
done

the local monitoring solution

You can create a local measure by doing
while [ 1 ]; do
    ./probe.sh | monitor.sh ;
    sleep .9;
done
We sleep only 1 second because my round robin archive (RRA) is set for a measure down to the second.

Distributing the measure


What if, the probes were using UDP4 broadcasting and the monitor were just ... lurking ?

There is a recipe for exactly this in socat documentation :
Example 2: Broadcast client and servers Broadcast server:
socat UDP4-RECVFROM:6666,broadcast,fork EXEC:hostname
This command receives packets addressed to a local broadcast address and forks a child process for each. The child processes may each send one or more reply packets back to the particular sender. Run this command on a number of hosts, and they will all respond in parallel. Broadcast client:
socat STDIO UDP4-DATAGRAM:192.168.10.255:6666,broadcast,range=192.168.10.0/24
This process transfers data from stdin to the broadcast address, and transfers packets received from the local network to stdout.
It's almost ready : on the computers where you want to deploy a probe just do :
socat UDP4-RECVFROM:6666,broadcast,fork EXEC:"./probe.sh"
To deploy a monitor do :
socat EXEC:"./monitor.sh" UDP4-DATAGRAM:192.168.1.255:6666,broadcast,range=192.168.1.255/24 
Now everytime monitor writes something on stdout, all the probes on the broadcast address will spill their data.

OOOps, the monitor does NOT write ... Ah ? Really ? Except if you kill it with a SIGUSR1 (trap "echo ping" SIGUSR1)... But wait ... we can actually launch as many monitor as with have available ips on the network ... But it ALL monitor talks we are gonna spam ourselves ...

Well, while we wait for a clean adaptative solution that monitors potential faults (net split for instance) to decide to trigger the signal of the clock we will stick a dumb one :
$ cat clock.sh 
#!/usr/bin/env bash
while [ 1 ]; do
    sleep 1
    MASTERID=$( cat mastermind.pid )
    kill -s SIGUSR1 $MASTERID
done
# clock.sh
And ... that's finished :D

Having fun with zfs snapshots and jails on freebsd : updgrading the zfs template of thinjails.

C'est en faisant n'importe quoi qu'on devient n'importe qui !
-- Rémi Gaillard (Montpellierain célèbre)
Since I decided to respin freeBSD servers since I have an allergy to systemd resulting in obfuscating simple things behind complex layers I put my fingers in my mouth : I set my actions with my words and do experimentations.

One of these experimentaiton is about playing with chroot (jails), zfs snapshot, and pkg. The frustration I have following the Freebsd handbook regarding creating thinjail is that you clone a BARE freebsd, and, as a sysadmin I am pecularly proefficient with bash... I want BASH installed in all my jails. Hence, I want to updgrade the base wich lies per manual advice in /usr/local/jails/templates/14.0-RELEASE and which is snaphoted with zfs without polluting the base with the install of pkg.

First thing let's check we being in a clean state :
#zfs diff zroot/jails/templates/14.0-RELEASE@base  zroot/jails/templates/14.0-RELEASE 
Let's add the local DNS to resolv.conf and see what happens :
# zfs diff zroot/jails/templates/14.0-RELEASE@base  zroot/jails/templates/14.0-RELEASE 
M	/usr/local/jails/templates/14.0-RELEASE/etc
-	/usr/local/jails/templates/14.0-RELEASE/etc/resolv.conf
+	/usr/local/jails/templates/14.0-RELEASE/etc/resolv.conf
Nice ! We want THIS to become the snapshot named « base ». How do we do per freeBSD zfs handbook ?
And well, I guess we take the safe path :
  • we modify the filesystem, add bash
  • we snaphost it
  • we check a new thinjail is up to date
Modifying /etc/resolv.conf is nice, but what about adding new packages to the base WITHOUT installing pkg cleanly ?

Let's jailify our template !

# more /etc/jail.conf.d/base.conf 
base {
  # STARTUP/LOGGING
  exec.start = "/bin/sh /etc/rc";
  exec.stop = "/bin/sh /etc/rc.shutdown";
  exec.consolelog = "/var/log/jail_console_${name}.log";
  # PERMISSIONS
  allow.raw_sockets;
  exec.clean;
  mount.devfs;
  host.hostname = "${name}";
  path = "/usr/local/jails/templates/14.0-RELEASE";
  ip4 = inherit;
  interface = wlan0; 
}
# service jail start base
Starting jails: base.

# pkg -j base install bash
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 4 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
	bash: 5.2.26_1
	gettext-runtime: 0.22.5
	indexinfo: 0.3.1
	readline: 8.2.10

Number of packages to be installed: 4

The process will require 12 MiB more space.
2 MiB to be downloaded.

Proceed with this action? [y/N]: y
....

#zfs diff zroot/jails/templates/14.0-RELEASE@base  zroot/jails/templates/14.0-RELEASE
M	/usr/local/jails/templates/14.0-RELEASE/etc
...
M	/usr/local/jails/templates/14.0-RELEASE/var/spool/lock
+	/usr/local/jails/templates/14.0-RELEASE/var/log/utx.lastlogin
...
+	/usr/local/jails/templates/14.0-RELEASE/etc/motd


The new « template » is a tad polluted, but it's nice.

It deserve to be kept as a base for a new jail template !
# zfs snapshot zroot/jails/templates/14.0-RELEASE@bash_base
And delete the jail we made to upgrade the package :
#service jail stop base
Stopping jails: base.
#mv /etc/jail.conf.d/base.conf /etc/jail.conf.d/base.conf.disabled

Now time to TEST !

# zfs clone zroot/jails/templates/14.0-RELEASE@bash_base zroot/jails/containers/testjail

# cat /etc/jail.conf.d/testjail.conf 

testjail {
  # STARTUP/LOGGING
  exec.start = "/bin/sh /etc/rc";
  exec.stop = "/bin/sh /etc/rc.shutdown";
  exec.consolelog = "/var/log/jail_console_${name}.log";

  # PERMISSIONS
  allow.raw_sockets;
  exec.clean;
  mount.devfs;

  # HOSTNAME/PATH
  host.hostname = "${name}";
  path = "/usr/local/jails/containers/${name}";
  # NETWORK
  ip4 = inherit;
  interface = wlan0;
}
# service jail start testjail
Starting jails: testjail.
# jexec testjail bash --version
GNU bash, version 5.2.26(1)-release (amd64-portbld-freebsd14.0)
#jexec testjail pkg
The package management tool is not yet installed on your system.
Do you want to fetch and install it now? [y/N]: 

Well, it is a success ! We successfully made an update of the base we cloned and checked it was taken into account at new jails instanciation, WITHOUT having to install pkg in the jail !

Un bon ouvrier se reconnaît à son plan de travail propre » (a clean workplace is the mark of a good craftsman)

Cleaning is as important as doing : we have to remove the test jail and the jails used for updating the base :
# service jail stop test
Stopping jails: testjail.
# rm /etc/jail.conf.d/testjail.conf
# zfs destroy zroot/jails/containers/testjail

Conclusion

There is a lot of nice solution to play with jails on freeBSD : ezjail (that I was using), iocage, AppJail listed in the handbook.
However, I really like the idea of working with the bare minimum from the handbook since it is well documented. It builds up a good intuition that framewoks like application will opinionate sometimes in different ways than mine. Before eventually switching to AppJail or iocage I want to have an understanding of the low level coupling between the operating system, the networks stack, zfs and jails works.

So far, the handbooks and documentation are very helpful, I did not even need to look at archlinux wiki pages, and my intuition seems to give results.
Freebsd compared to linux has become for me a way to get a grasp back at reality, I profoundly understand again the founding layers of the system.
As such I would rate BSD experience as rejuvanting and dispelling the churn of technology.

Why use docker when I have jails ? AppJail even propose a deployment process that is a functional copy of docker. I have linuxlator and debbootstrap to install debian based linux jails, and bhyve as the equivalent of qemu.

I have been burnt with k8s mammothesque software defined stack making both DNS resolution and routing an obscure task, making a friction to deploy containers. Right now, I spin clean containers for everything that I want to contain and none of the containers are used for containerisation (like windows that actually MUST spin a linux VM or WSL2 to handle docker). It does make things less bloated.

The simplicity of rrdtool as a database

rrd is the sqlite of time series database it does two things well : update the archive (which cacti, nagios, munin > ...) knows fairly well how to update, but it also is an archive format.

When you are on a distant server, you may not have access to a web browser, nor do you want to install Xserver (or wayland) locally to see the data.

Here is your savior : pkg install gnuplot-lite. A version of gnuplot aiming at graphing plots on the terminal in ASCII.

First, let's assume we work with munin wich by convention put only one data source per archive, and name it « 42 ». It is a wise choice to avoid confusion and have the memory of where data source are stored at the price of having a lot of rrd files.

Hence, by convention our rrd are named host.group_plugin_name_of_datasource.rrd.

To extract the data store we need the points
LC_ALL=C rrdtool fetch  badass.home-cpu-system-d.rrd AVERAGE
will extract the points without LANG=fr changing your decimal separator.
If there is one command to remember for plotting with gnuplot: this is the one. If you remove the « : » you have the exact expected input from gnuplot for a plot.
$LC_ALL=C rrdtool fetch pierrot.home-cpu-system-d.rrd AVERAGE |\
    perl -ane 'm!^(\d+): ([\d\+\-\.e]+)$! and print "$1 $2\n";' \
    | head
1718192400 1.7250666667e+00
1718192700 1.6645333333e+00
1718193000 1.6012666667e+00
1718193300 1.6555333333e+00
1718193600 1.6632000000e+00
1718193900 1.8789333333e+00
1718194200 1.6220000000e+00
1718194500 1.7081333333e+00
1718194800 1.6512000000e+00
1718195100 1.7545333333e+00
Hence with gnuplot dumb output :
$LC_ALL=C rrdtool fetch pierrot.home-cpu-system-d.rrd  AVERAGE |\
	perl -ane 'm!^(\d+): ([\d\+\-\.e]+)$! and print "$1 $2\n";'|\
    gnuplot -p -e "set xdata time;set terminal dumb 60 40 ;
    	set timefmt \"%s\";set xtics rotate by 45 right; 
        set format x \"%m/%d/%Y %H:%M\"; 
        plot \"-\" using 1:2 with l lines \"-\""

                                                            
  10 +--------------------------------------------------+   
     |   +   +   +   +   +   +  +   +   +   +   +   +   |   
     |                            "-" using 1:2 +.....+ |   
     |                                                  |   
   9 |-+                           +                  +-|   
     |                             :                    |   
     |                             :                    |   
     |                             :                    |   
   8 |-+                           :                  +-|   
     |                             :                    |   
     |                             :                    |   
     |                             :                    |   
   7 |-+                           :                  +-|   
     |                             :                    |   
     |                             :                    |   
     |                             :           +        |   
   6 |-+                           :           :      +-|   
     |                             :           :        |   
     |                             :           :        |   
     |                            ::           :        |   
   5 |-+                          ::           :      +-|   
     |                            ::           :        |   
     |                            ::           :        |   
     |                            ::           :        |   
   4 |-+                          ::+          ::     +-|   
     |                            ::+          ::       |   
     |                            :::          ::       |   
     |                            :::          ::       |   
   3 |-+                          :::          ::     +-|   
     |                            :::         :::       |   
     |                            :+:         +::       |   
     |                            :::         :++ +  +  |   
   2 |-+ ++++++  +++      +++  + +:::++ + + + ::: +++:+-|   
     |  ++++++++++++++++++++++++++++++++++++++++++:++   |   
     |   +    +  ++ ++++ ++ +    +    +  ++ +     ++    |   
     |   +   +   +   +   +   +  +   +   +   +   +   +   |   
   1 +--------------------------------------------------+   
 06/106/106/106/06/106/106/106/106/106/106/13/2024 12:00    
                                                 
                                               
This means, we can now write a script that can both be used as a terminal plotter of rrd archive, but also as a gallery viewer : It seems fun and all, but what about looking at the value of two distinct data source on the same graph to see if they are correlated.

Let's say I want to compare my usage CPU and the sum of my network interfaces as a ratio of their max to see if they are related ? How complex is it ?

Well actually rrdtool export (man rrdexport) provides a tool for exactly this.

It's a FORTH based pipeline operator on views of time series here is an example.

Let's say we want to compare our CPU usage and our incoming + outgoing network trafic. It needs 3 operations :
  • one additions of the network output and input
  • two normalization by 1 so that we can compare on the same graph
LC_ALL=C rrdtool xport -t  -e now \
    DEF:x=pierrot.home-ibm_acpi-CPU-g.rrd:42:AVERAGE  \ # we define x as average of CPU temp
    VDEF:y=x,MAXIMUM \                                  # y = max(x) (FORTH X,MAXIMUM)
    VDEF:l=x,MINIMUM \									# l=min(x)
    CDEF:z=x,l,-,y,l,-,/                                # z=(x-minx)/(maxx-minx)
    DEF:a=pierrot.home-if_wlan0-obytes-d.rrd:42:AVERAGE \ # a = incoming traffic
    DEF:b=pierrot.home-if_wlan0-rbytes-d.rrd:42:AVERAGE \ # b = receiveid traffic
    CDEF:c=a,b,+ \                                      # CDEF for adding rank by rank operation in FORTH
    VDEF:d=c,MAXIMUM \                                  # VDEF for the whole series (ex percentile)
    CDEF:e=c,d,/ \                                      # normalization
    XPORT:z:ratio \                                     # export ratio z
    XPORT:e:ratio                                       # export ratio e
    
 
If you export it as json you just need to pipe jq to get a gnuplot default input :
 jq -j -c -r '.data[] |  .[0] , " " , .[1], " ", .[2] , "\n"' > temp.csv
 
You take the array defined at the key for data. The -t option of rrdtool xport makes sure data[][0] is the time and the following one, the one specified in the xport directive.

Then, the reminder is the gnuplot that gives the following result :
And now we can make a nice CLI tool to compare two rrd from the command line with output in ascii art Giving the following result
X=80 Y=40 ./hf.sh pierrot.home-ibm_acpi-CPU-g.rrd pierrot.home-hddtemp_smartctl-ada0-g.rrd 

                                                                                
    1 +---------------------------------------------------------------------+   
      |     +     +     +    +     +     +    ##     +     #   ##     +     |   
      |                             pierrot.ho##-ibm_acpi-C#U-g##rd +.....+ |   
      |                    pierrot.home-hddtem##smartctl-ad#0-g##rd ####### |   
      |                                       ##           #   ##           |   
      |                                      ###           #   ##           |   
      |                                      ###           #   ##           |   
  0.8 |-+                                    ###           #   ##         +-|   
      |                                      ###           #   ##  +        |   
      |                      ###############################   ##  :        |   
      |                      #                                 :   :        |   
      |    +                 #                                 +   :        |   
      |    :                 #                                 :   :        |   
      |    :                 #                                 :   :        |   
  0.6 |-+  :                #        +       +    +          + :   : +    +-|   
      |    :                #        :       :    :          : :   : :      |   
      |    :                #        :       :   +:     +    :++   : :      |   
      |    :        +       #        :     ++: + ::    +:  ++:::   + :      |   
      |    :        :    ## #        ::    ::: : ::    ::  :::::   :::      |   
      |    :        :    ## #       +::++++:+: :+++ +++:+++:::+ : +++:      |   
      |    :        :    ## #       ::::::::::::::: ::::::::::: : ::::      |   
      |    :        :    ## #       ::::::::::::::::::::::::::: : ::::      |   
  0.4 |-+  :        + +  ## #       :++++:++++++++++++:++++++++ +++:++++  +-|   
      |    :       :: : # ##        ::   :  : :   ::: : ::::::  ::::  ::    |   
      |    :       :: : # ##        ::   :  : :   ::  : ::::::  :::+  ::    |   
      |    :++++  +:+ + # ##        +:   +  + +   ++  + ++++:+  +:+   ++    |   
      |    :::::  ::::: # ##        ::                      :    :          |   
      |   ############### ##        :+                      +    :          |   
      |   +:+:++++##:++++++:        +                            :          |   
  0.2 |-+ ::::: ::##: :::   :       :                            :        +-|   
      |   ::::: + ##: + +   +       :                            +          |   
      |   :: ::   ##:   :   :       :                                       |   
      |   :: ::   # :   :   :       :                                       |   
      |   ++ ++   # +   +   :++++++:                                        |   
      |           #         ::::::::                                        |   
      |     +     #     +   :+::::::     +     +     +     +    +     +     |   
    0 +---------------------------------------------------------------------+   
  06/12/06/1206/12/06/12/06/13/06/13/06/13/06/1306/13/06/13/06/13/2024 12:00    
                                                                                

As you noticed in my example : rrdtool xport is giving you the basic of treating/transforming datasource in rpn, and graphing is just a few steps away from exporting and it gives the following results :
At the end of the day, there is a great frustration using rrd : it is an amazing under used, uncorrectly documented tool. Most of the power of rrd lies in obscure features such as xport that requires a better explanation of how the forth works, like for instance how we can build a custom aggregation function (recoding a moving median as an example would be nice). However, I still find it a fun tool to toy with.

How it feels to light up your new freeBSD server as a linux raised sysadmin ?

TL;DR Using freeBSD is like sailing the seas, whereas linux is more like having fun with a brand new shiny boeing 737 MAX.
So, what I like are factual, damn practical stories.
It began with a need : a damn bloody simple backup server.
And no complexities here : I have only linux and BSD computers that all have deployed ssh keys, hence rsync over ssh seems to be the « let's do first, improve later » kind of thinking.
It only requires ssh + rsync, git and a ... DNS resolver (unbound), because ISP DNS blocking is a thing in my country and a backup server might have to talk (git) to push/pull external data.

Unbound is cheap in resources, easy to install and a perfect use case for having fun with zfs thin jails.

Last time I had self hosted domain on a freebsd server I used ezjail because as a noob I flet secured.

Workinig with the freebsd handbook and the raw command is way more securing. I even did some nullfs mounting for the fun and for practicality. It is a sane alternative to symlinks.

Il also love to write the jails config file because their grammar is human readable and concise. It's almost like writing an haiku or a sonnet : a concise form of poetry.

Let's say that BSD being BSD, unices being unices, linux and bsd being close setting up the backup went fast. It was the work of a very-slow day from install to setup.

I did reinstall a few time, and I think interesting to share my though on disk encryption : why I wiped out my fully encrypted disk setup. It was impractical to cut myself from a reboot without a human behind the keyboard when a BACKUP server, might comme to be fucking necessary to be accessible. (I have lived abroad as an immigrant scared of being expulsed because of papers and I have a paranoïa about having backups of IDs first existing, and secondly to be easily accessible from the outside in case I am restricted the physical access to my house and need to prove my official identity FAST.).

So, yes, our use case of backup varies with our past experiences, including the ones of disasters that makes every sysadmins' risk sensitivity vary with their life.

So yes, you want to able to maintain a server while not having physical access to it, doing updates (of kernel drivers for instance) that may require reboot. And, you can still cipher the home dirs of the users.

So practicallity beats purity : physical access to my computer is easy and has the boot invite in single mode for password recovery, enabling root to impersonate and read the data. On the other hand, my physical threat model inherited from my life trauma is not someone breaking into my house (I have experienced it), but me being taken out of my house and needing urgently papers to prove my identity.

Plus in case of burglary, my server is a broken 15 years old computer, with a broken screen and a centrino sticker. Not really the kind of stuff you steal.

So yeah, I have a huge security hole when it comes to the physical dimension based on my risk assumptions which diverge from common experience.


As you can see, from the week end to monday, I filled 60% of a disk with backup, and I also installed a supervision, and a web server, even though they are increasing uselessly the surface of vulnerability.

It's one of my divergence with a lot of sysadmins that love to spin kubernetes or heavy containers with one VM per task. Me, I prefer my jails : they are both a container for security, but also for the mess of depencies.

You see thanks to zfs, each jails cost me less in terms of disk space, they are almost free after the first one, the same cannot be said of docker, qemu and vmware. My jails balloon (take more shared space) on the disk without me wasting space, and energy supervising hosts and guests' disks space just « in case ».

Also, jails are a localized mess due to the depency hell. They sometimes require modifications in rc.conf that are not wishable on the host or depencies to like wayland that you would like to disappear if you change your mind about this package. Jails are not only software containers, they are also a container of the mess of installing to much service on an operating system. And with /usr/ports I can have a nice and boring safe and conservative behaviour with the host sysadmin management and get totally nuts with bleeding edge versions in some jails without messing up with the host.

And since it's only chroot, I can copy files from all jails and the hosts without any layer of complexity.

So at 9am the backups kick their life, because, by reminiscence of my past life as a poor, I did a 9 to 5 server. The kind that can be shut down to let people sleep, or to be moved away fast without anything breaking.

The kind of companion that silently slurps data being pushed to it if it is there. The advantage of rsync over ssh from the backuped computer is that on the backuped computers you have a live memento in the crontab of your prefered arguments on rsync to deploy a new backup server.

Most of my difficulties in my plan has been the lack of cooperation of linux in overriding the dhcp settings to supersede the local dns. Modern Linux are pissing me off when it comes to DNS configuration. At least with BSD I know /etc/resolv.conf is the solution. Because, SINCE I am sysadmin, I love making X509 certificates that are self signed and REQUIRE a DNS warrantying that the direct name and RPTR for the IP are same.

I don't like HTTPS, but you have to fucking idiot to let a plain http server in a setup where you put HUGE security holes. And you want your certificate to be included in the openssl wallet, as well as firefox. So you do it slow and nice..

# Mordor authority on .home
openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout RootCA.key -out RootCA.pem -subj "/C=VX/CN=Mordor"
# in em format
openssl x509 -outform pem -in RootCA.pem -out RootCA.crt
touch home.ext
# make me a certificate for www.home 
openssl req -new -nodes -newkey rsa:2048 -keyout www.home.key -out www.home.csr -subj "/C=VX/ST=Vexin/L=Toulouse/O=Sauron/CN=www.home"
openssl x509 -req -sha256 -days 1024 -in www.home.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile home.ext -out www.home.crt
# put in the jail
cp www.home.{crt,key} /usr/local/jails/containers/www/usr/local/etc/nginx/
# restart the nginx in the jails www
jexec www service nginx restart
# update this dir that is used by openssl to store openssl certificate
openssl rehash .
I know solutions like lemur exists to handle SSL Authority and that they are awesome. But the lazier I am with openssl command line, the less proficient I am when all hell break lose and I need to fire muscle memory with openssl to manipulate or check certificate.

So now it's monday, 10 am, I am doing my ssl certificate for my nginx because I decided to install munin.
Munin is a very old suboptimal supervising solution that has not been updated in years, I use it as a first tool because :
  • I know basic probes cover 95% of my needs
  • I know how to write a plugin fast for it
A more optimal solution would have been checkmk it it covered BSD correctly, nagios if it was not that heavy as shit, cacti that is overengineered, zabbix ...

But I always rush to munin because I know I can deploy it fast and that it generates STATIC web pages with a crontab (meaning I don't need any cgi's PHP or java). And it can gather up data out of the box from the other stations (thanks to broadcast).

Well, a linux sysadmin, I was disappointed munin on freeBSD does not covers as much. I had my most important ones :
  • obvious ressources (RAM/CPU/Disks/Net)
  • SMARTD - you should NEVER underestimate how much SMART (self reporting tools for hard drive) are important for non SSD hard drive.
But I was missing :
  • ACPI temperature
  • fan speed
So, I googled a tad, saw I needed the kernel module ibm_acpi to access the data and fell short of motivation when I saw I had the temperature but not the labels.
Raised as a physicists I don't do any graphs without label. So I asked miod (the most reverred guru of french BSD community) where the data were.

And the guy said
Selon acpi_ibm(4) :

     dev.acpi_ibm.0.thermal
             (read-only) Shows the readings of up to eight different
             temperature sensors.  Most ThinkPads include six or more
             temperature sensors but only expose the CPU temperature through
             acpi_thermal(4).  Some ThinkPads have the below sensor layout
             which might vary depending on the specific model:

             1.   CPU
             2.   Mini PCI Module
             3.   HDD
             4.   GPU
             5.   Built-in battery
             6.   UltraBay battery
             7.   Built-in battery
             8.   UltraBay battery
  

And that's the nicest RTFM I have experienced in my life. And that should remind you of one of the FUNDAMENTAL difference between linux and BSD.

The fresh up to date information is almost always in your man page and not on the internet.

Which lead me to thank him, and move my lazy ass to write the plugin out using the linux ACPI as a template in 30 minutes. I love the BSD community they are always nice.

Here is the code.

Here is the graph :

And here, just after the munin plugin kicks off : you see me panicked at the view of the CPU burning at 80°C and put a fan on the computer to make it cool down at more reasonable temperature.

I very swiftly reacted and checked if by any chance I did not missed a package to activate the fan. Of course I missed the bsdfan package, that lacks a service so you have to write a service.
It took me 5 minutes of googling to have the script :
[root@petiot /etc/ssl/home]# 
more /etc/rc.d/bsdfan

#!/bin/sh
#
#

# PROVIDE: bsdfan
# REQUIRE: DAEMON
# BEFORE: LOGIN
# KEYWORD: nojail shutdown

. /etc/rc.subr

name="bsdfan"
desc="Modify the fan according to temperature"
rcvar="bsdfan_enable"
command="/usr/local/bin/${name}"
bsdfan_flags="-d"

load_rc_config $name
run_rc_command "$1"
It damn beats the speed at which I can deploy a random script as a service with systemd. And by removing the external fan and experiencing the drop of termerature I had a clear hint it was working.

So for fun I added a probe on the rotation of the fans :

As you can see, I could have missed the fan problem since most of its time under usual load the fan is turned OFF.

Well, at the end of the day, this caveat made me like freeBSD even more.

Having to improvise adapt, overcome it part of the sysadmin life. Having a small turbulence at the beginning of a life of a server is a good way of battle proving the choice.

At the opposite of linux, BSD relies a lot on shell (/bin/sh) as a DSL for the config and setup as a one ring to rule them all.

On the other hand CLI experienc of linux is way more diverse having json/ini files/custom XML ... as a text interface to interact with the core of the system. The BSD clearly is more consistent and easy to use from command line making it easy for you to customize it in a clean way. You have the impression to wake up from an heavily loaded smoke of bullshit when you realize how simple containerisation can be, tweaking the system can be, in a sane way.
My biggest grief with linux right now is not technical, but the user experience on the command line that is an absolute mess. I hate to have more than one way to setup network bridges (ip2+brctl) I totally love to do it with ifconfig in a consistent way.
I have to learn one grammar for parsing and templating most of the sysadmin tools/config : and it's almost always /bin/sh feeling. It really remove the accidental brain fog that stands between me and getting things done in a short time without a mistake.

Chroots may not be as sexy as docker, but they are lighter for an almost equivalent service and awesomely well integrated with the os, you should use them more. I can even deploy debian based jails finger in ze nose with linux jails, while linux sysadmins require hypervirtualization (qemu, vmware) to deploy a freebsd box among their servers.

In terms of sysadmin experience, freeBSD is like removing a lot of brain fog coming from over-complication, it is simpler, more conservative and easier to hack CLEANLY.

I really encourage you to have fun with my automated freebsd customisation for qemu.

PS thanks to benoit for this server.

PPS : I feel so relieved to have my backups again.

Sauvegarde et détente, enjaillons le week end !

Le truc que j'aime pas c'est les sauvegardes (backup en fr_paris).

Non, pas que la vie m'est maintes fois prouvées leur utilité, mais le nombre de fois où mes mauvais choix m'ont mis en stress par absences de sauvegardes.

L'art de la sauvegarde doit être menée non par des scribes, mais au coin du feu en mangeant des chamallows grillés et en s'interrogeant sur nos valeurs.

  • Sont-elles celles du sysadmins qui veut faire un truc chiadé et complexe sans couture ? (juste ça marche avec de la magie en dessous)
  • Celles de l'utilisateur (que je suis aussi) qui veut qu'on change pas ses habitudes et que marche sans coutures (et sans magie)
  • Le serial loser qui a donné dans les illusions du sysadmin et de l'utilisateur qui ne peut que constater les échecs répétés de ces deux stratégies


Il est temps de regarder les étoiles et de changer la manière dont on fait sa politique de sauvegarde en passant « battle tested » et « battle rejected ».

Actuellement, les documents numériques important que j'ai là, là, et que je veux sauvegarder sont de fait mais sauvegardes de pièces numériques ... Donc, j'ai en fait déjà un backup. J'ai peut être sérial losé, mais j'ai rattrapé de sources éparses en plein vols des sources et des copies de documents réels qui m'ont sauvé la vie.

Quelque part, je devrais souffler et me rappeler en regardant les étoiles et le ciel dégagé, que la foudre va pas me frapper de suite. Vu que j'ai aussi les pièces originales des copies que je sauvegarde.

Donc battle proven : AVOIR DES SAUVEGARDES C'EST BIEN, c'est même pour ça que je peux penser au sujet sans urgence.

En parlant de temps, et de serial loser, j'ai des vieux ordis que j'utilisais en serveur de sauvegarde, il est peut être temps de les rallumer pour voir ce qui traîne dessus...

Lol...

Content que les freeBSD soit conservatifs, car la procédure pour récupérer les mots de passes depuis le boot a pas changer. (noter ça dans bien et pas bien).

Une fois connecté, j'ai trouvé des photos non backupées que je voulais récupérer...

Sauf que le ssh était trop vieux.

J'ai voulu mettre à jour ssh, mais, les certificats SSL étaient tous expirés...


Bref, il me restait toujours le tournevis et une nappe pour disque 2.5"...

Mais j'ai réflêchi au lieu d'agir ... en me demandant ce que j'avais fait de bien et de négatifs dans tout ça, dans cette machine qui reboote...avec smartd annonnçant la fin, et encore un peu de temps pour récupérer les données uniques à cette machine ?

Déjà, j'ai eu raison à l'époque (2009) de prendre un mini pc comme serveur : ça m'a permis de l'emporter autour du monde, et de pouvoir toujours le réparer .... et d'imaginer lui donner une deuxième vie.

Ensuite, ce qu'il y a sur le serveur, c'était de la démo, et de la config de nom de domaine (auto-hébergé) ... ben ça, j'en ai plus besoin, et 60 photos dont 39 ratés, et 10 en doublons, ça peut s'oublier...

Bon, je vais les ramener, mais je m'en fous un peu, c'est pour ma femme qui aime faire des albums photos des lieux où l'on a vécu. Et on a pas beaucoup de photos de Montréal.

Bref, la sauvegarde c'est aussi une réflexion sur ce qui a de la valeur ou pas, et jusqu'à quels efforts on est prêt pour récupérer de la donnée.

Chaque complexité qu'on rajoute (OS, hardware, périphérique, taille) est un obstacle à récupérer les données.

C'est un travail d'orfèvre en ascétisme fonctionnel, le moins de parties « mouvantes » possibles, le plus de fonctionnalités possibles, mais on hésite pas à en sacrifier... (Ainsi que des données)...

Ce sera la job de ssh/sftp.

En plus c'est parfait freebsd propose déjà git-shell comme login restreint pour les comptes utilisateurs. Je peux aussi penser à migrer mon code quand je sens le krash boursier qui pourrait contraindre les comptes gits gratuits à disparaître sur l'autel de la réduction de coûts.

Sur ce coût, je vais être survivaliste git : je vais me r'auto-héberger. Ça fait qu'un seul protocole à sortir : ssh et en plus ça me permet de faire une stratégie de backup.
Qui a besoin de web en externe quand t'as un ssh en dmz ?

Tu as vraiment besoin du web ? Tu le ssh tunnelise depuis la DMZ et t'ouvres 0 ports.

Ben, c'est pratique un backup accessible de manière sécurisée depuis l'extérieur, non ?

Pour synchroniser une journée de code sur un projet sous git ...

Un serveur sécurisé, est un serveur surveillé, et la meilleure des surveillances c'est l'utilisation quotidienne, qui est l'alarme la plus précoce (après smart) de défaillance et besoin de maintenance.

Autrement dit, le paradoxe de la sauvegarde est de penser immédiatement un point unique de concentration des données. Un beau « Single Point Of Failure ». Mais en fait non, la situation change que l'on cause de photos (dont je me fous un peu) ou de code.

en code, quand je mets à jour mon git local, je fais une copie parfaite du dépôt distant. L'utilisateur local devient mon backup.

Malheureusement pour les assets statiques (photos, mails, documents) on a pas encore trouvé le graal du git qui sait se débrouiller avec la gestion des fichiers binaires.

Donc, bon, vu que j'ai résolu un choix de priorité, perso, je vais m'intéresser à donner une copie transparente aux archives.

Et ça tombe bien avec freeBSD j'ai openZFS, qui me permet de faire une redondance mirroir avec l'ajout d'un disque physique. Et comme ZFS est encore plus standard que lvm c'est mieux documenté. Lol.

Bref, je pourras penser à faire un backup distant plus tard à mondre coût avec rsync, et voilà. Il est temps d'arrêter de rêvasser et de terminer les tests d'utilisabilité de nautilus avec des dossiers montés à distance en sftp/scp pour que ma femme y mette ses photos.

Pour une redéfinition citoyenne du temps : tout ce qui ne va pas avec le temps (et ce qui pourrait aller mieux) !

Le temps est l'accident des accidents.

-- Démocrite
Le temps existe en de nombreuses saveurs toutes aussi légitimes à être évoquées les unes que les autres :
  • le temps de la physique qui permet de bâtir les horloges
  • le temps astronomique qui donne les heures de levers et de couchers du soleil sur lesquels le vivant est aligné
  • le temps des religieux et de leurs prières
  • le temps des supertitions Babylonienne qui nous ont légué les divisions en mois et heures/minutes/secondes
  • le temps de la logistique qui fait que les trains arrivent à l'heure
  • le temps de vivre
  • le temps de la météo qui apporte des pics d'énergies renouvelable
  • le temps du braco du temps jadis où le papet à Pagnol se réveillerait non plus à 5h du mat' pour aller braconner mais 7h du matin heure actuelle (avant sa redéfinition en 1942)
  • et enfin le temps dicté par le fait politique qui dirige nos vies quotidiennes et l'année par l'imposition de décisions arbitraires questionnables
La question qui devrait interroger le politique est : notre définition du temps qui est la plus impactante est elle bénéfique ?

Poser cette question, c'est aussi introduire l'idée que l'on peut MESURER un impact de la définition du temps en la comparant à d'autres échelle de temps. On notera que le temps politique a adopté comme norme social :
  • une durée du jour de 24h00 (temps astronomique théorique) qui ne correspond pas à la réalité physique
  • une durée d'année de 12 mois non régulier avec des morceaux d'anciens cultes païens (genre Héphaïstos est boîteux comme le mois de février), relativement astronomique (découpage en saison)
  • un temps synchronisé sur tout le territoire malgré en métropole une divergence de 30 minutes entre l'heure solaire et l'heure de l'horloge
  • un temps découplé de ceux des animaux et des rythmes circadiens humains qui détestent les changements horaires
  • des multiples définitions conflictuelles du temps dans la loi au regard du type de contrat pourvu qu'il soit de location d'un bien (calendaire/mensuel) ou d'une force de travail (journalier à temps mensualisé) ou d'une propriété intellectuelle
  • des cycles pluri-annuels de rituels tragi-comiques sociaux appelés élection qui résultent dans l'incapacité d'entreprendre un projet d'ampleur sur plus de 2 ans
  • le temps des demi vies des radioactivité des atomes de plutonium (10 000 ans) avec lesquels l'état nous a maqué (voir point juste au dessus)
  • la vitesse de transition vers le dérèglement climatique que les mesures politiques accélèrent...
Tout ces leviers que le politique a sur le temps devrait pousser philosophiquement à ne plus considérer le temps comme une constante à conserver, mais un paramètre dont il est évident qu'en ce qui concerne le temps de l'horloge qui est sur le bureau de mon ordinateur, où l'horloge murale qu'il est un temps par essence POLITIQUE. Qui dit qu'il est politique dit : on peut le changer. Qu'on puisse le changer est un fait, le corrolaire d'un impact bénéfique est le seul sujet à discuter.

Le temps est une construction POLITIQUE et historique

Si le temps était physique alors, je n'aurais besoin que d'instrument idoine pour le mesurer.

Avec l'ombre portée d'une baguette je peux mesurer l'heure solaire. Je peux découper de manière fiable une journée en : lever et coucher du soleil, zénith.
Qui a « décidé » de manger à midi (au zénith) ?
Les organes sociaux au moyen âge pour synchroniser les chantiers avec les marchés.

Nous en 2024 on mange très bien à 14h heures solaires depuis 1942 et ça gêne personne. On peut dire avec 80 ans d'expérience que cette heure arbitraire peut être changée sans impact.

Le temps est une réalité physique qu'il est risqué de changer

Grâce aux riches qui aiment à voyager sécuritairement, l'impact du temps politique sur les humains est scruté par le BEA (Bureau Étude Accident) à Balma (31000).

Si un secteur a mis en évidence les problèmes liés au temps politique et son impact en morts c'est le transport aérien de tourisme. Les rapports sur la nécessité de bien dormir et les impacts des fuseaux horaires.
On retrouve les mêmes résultats en accidentologie routière : le changement d'heure saisonnier TUE.
Le coupable que cette analyse par situation avant après met en évidence est la perte d'alignement entre l'horloge humaine du sommeil et l'horloge politique d'une part et l'incapacité à trouver un temps absolument optimal.

Dès qu'un temps est fixé, on fait des mécontents et des contents. D'un coté on épargne de l'énergie, de l'autre on créé des accidents (chose pour laquelle l'état devrait être poursuivi pour sa responsabilité pénale).
Le changement horaire a minima est CRIMINEL, non par le choix d'un bon ou mauvais fuseau horaire, mais simplement de par son existence.

Un temps politique meilleur devrait être défini « sans changement de fuseaux horaires arbitraires ». Seulement voilà, le système est en place, il y a un coût à l'abolir, comme il y a un coût et des profits à maintenir cette entité abstraite (constellation GPS, horloges atomiques, serveurs NTPs, armées de codeurs jonglant avec la souplesse du temps et des bugs que ça entraîne...).

Si on supprime le changement horaire bi-annuel, par quoi le remplace-t'on ?



Le bonheur des uns fait-il le malheur des autres ?
Si un argument revient en France POUR le temps solaire + 2h, c'est bien le temps libre : de fait la journée de travail en heure solaire n'est pas 9h 17h mais 7h 15h laissant en été une longue plage de jour dont on peut profiter. Le touriste en profite (et la balance commerciale aussi) notamment parce que le fuseau horaire sur l'UE est majoritairement celui de Berlin. Le touriste européen n'a même pas de décalage horaire à subir, il vit comme si habitait pas à 2000km heure solaire de là ! Toute la société est décalée pour lui de 2h ! La logistique est en joi aussi : pas de tables de correspondance des horaires en fonction des territoires à passer.

L'union européenne est une union temporelle qui se superpose à l'union douanière (die Zollverein Union von Bismarck, ach ach ach).

Avons nous intérêt à changer ? Là encore, on voit un coût cacher à changer : celui de créer des dis-satisfactions avec nos voisins commerciaux pour lesquels notre intégration dans le fuseau horaire européen est un plus.

Mais enfin, j'ai pas besoin de faire un dessin à ceux dont les grand pères étaient bracos : la nature animale de l'homme n'est pas régi par une horloge, mais bien le soleil..

Une société où l'on se léverait absurdémment à 19h pour travailler et on irait se coucher à 9:00 ne semble pas une solution d'avenir. On empiète sacrément à un moment sur la santé de la population, et notamment des enfants.

Si 12h sont évidemment TROP, est-ce que 2h comme aujourd'hui sont mesurablement délétères ?

A-t'on une expérience en cours sur 1.2 Milliards d'êtres humains en double aveugle qui courre depuis que l'Inde a mis un fuseau unifié en place depuis 1906 ?

Le résultat est sans appels pour ceux qui comme la France sont à l'Ouest du décalage horaire : Les effets délétères sur le sommeil des enfants se traduisent en pertes sonnantes et trébuchantes du PIB par effet papillon. La perte d'alignement avec le rythme circadien à l'OUEST à 2h du centre entraîne la perte de sommeil qui entraîne de mauvais résultats scolaires.

Si tu veux améliorer les résultats scolaires en France, tu changes simplement le fuseau horaire sur lequel on vit: et hop, miracle tu donnes de meilleurs résultats scolaire à TOUS les français.

Enfin, on peut toujours chipoter : si l'Ouest paie cher avec 2heures, la différence Strasbourg Rennes (29 minutes solaires) n'est elle pas une inégalités flagrante des citoyens devant le temps. Avec les Alsaciens favorisés par une norme arbitraire sur les Bretons en qualité de sommeil ?

Mais a-t'on envie d'avoir des horaires de trains qui supportent 10 zones horaires sur le territoire ?

J'ai envie de dire, le coût des zones horaires est purement informatique de nos jours, on sait faire des montres qui changent de fuseaux automatiquement en fonction du lieux. Il n'y a techniquement aucun argument contre 20 zones horaires en métropole, c'est juste que ce serait le bordel pour la logistique.

M'enfin, on pourrait tout à fait donner à la logistique le droit de gérer son propre fuseau unifié, qu'on appelerait le temps universel logistique géré par l'Organisme International du Commerce.

Oui ... MAIS ... plus les fuseaux horaires sont découpés, plus ça défavorise mon accès à l'Ouest (le soleil se couche à l'Ouest) car mes entrepôts ferment plus tôt dans ce sens.

Clairement se détâcher du fuseau de Berlin couperait la France d'une partie du transit vers l'Ouest à cause des fermetures « anticipées » des infras, de l'autre, elle verrait ses ports gagner organiquement du traffic face à la Hollande grâce aux 2h d'ouvertures précoces des ports fluviaux, aéroportuaires et maritimes.

Il me semble que je suis biaisé en faveur du temps comme étalonné sur le rhythme circadien optimal de l'humain, ce qui est soyons franc : le temps solaire. Grand père était braco par la force des talents acquis en fuguant (sans jamais revenir). Quand tu braconnes, tu t'en fous de l'horloge de la mairie ou de l'église : tu suis le soleil et le gibier. Tu vas avec la biomasse, comme le pasteur qui se réveille, où le prof qui appelle les élèves.

Malgré mon biais je pense comme le sophiste Protagoras que l'hommme et la femme sont la mesure de toute chose. Et comme les sophistes qui étaient opposés au philosophe/technocrate roi, je ne pense pas que la décision de choisir l'arbitraire d'une nouvelle norme sociale pour le temps puisse -en dehors de la logistique où c'est acquis qu'il y a besoin d'un temps synchronisé technocratique- être acceptable.

Il me semble évident qu'une société saine devrait avoir la folie temporelle d'avoir deux horloges : celle d'un temps synchronisé mondial, et celle locale corrélée sur notre quotidien qui est fait d'interaction avec la logistique mondiale (commerce), et les troupeaux (là encore, c'est aussi bon pour le commerce de ne pas stresser les vaches et agriculteurs). Évidemment que cela crée des tensions : l'agriculteur voit dans ses coûts énergétiques l'influence de l'heure logistique qui a tendance même si on le forçait à changer d'heure à l'inciter à vivre quand l'énergie est pas chère.

Aussi dans une moindre mesure, on veut que le temps locale soit localement un temps logistique, sinon, ça va être dur de réceptionner les marchandises, ou ne serait ce que se faire livrer une pizza si on est pas d'accord sur les durées acceptables de flottement.

Ouais toute la france à l'heure du quart d'heure toulousain et ça pourrait ruiner un pays.

Il y a j'avais oublié le temps culturel qui n'est pas dominé par l'influence de la latitude, mais de la longitude. Ma femme et moi sommes dans le camps des ponctualistes des cultures nordiques. Au sud de la Loire, le premier décalage horaire, c'est celui de l'acceptabilité sociale « d'être à l'heure avec entre un quart d'heure et plus de retard selon la ville ».

J'imagine que les premières Nations de Guyane ont aussi un rapport culturel au temps qui n'est pas le même que le notre, et qu'il y a une violence culturelle à imposer notre arbitraire du temps à leur culture.



Plaidoyer pour un temps démocratique

L'erreur est de penser que les rituels enkystés dans le temps comme les élections sont démocratiques : ils sont le contraire.
La démocratie se définit par des mécanismes d'améliorations qui profitent à tous sans distinctions de statut social. La démocratie se mesure à la capacité à être le plus inclusifs possible d'un système quand il change.

Un état - ryhtmé par des rituels - c'est une stase. Tout le contraire d'un changement. Rien qu'en figeant les choses la philosophie même de rituels, et de conservatisme sont en conflit direct avec un idéal démocratique qui est populaire et que les philosophes-experts appellent populistes.

Nous avons quelque soit le chemin vers un temps démocratique devoir accepter la nécessité d'un mal d'un temps logistique, technocratique.

La logistique est le nerf dans une guerre, et pour se préparer à n'importe quel conflit, on a besoin d'un temps synchronisé monotonale croissant qui donne un « la » temporel global comme le chef d'orchestre.

Quelque soit le besoin d'un temps technocratique, ce temps technocratique DOIT être le plus possible capable de vivre en établissant la passerelle avec le temps circadien.

Ça sert à rien de vouloir avoir la meilleure logistique du monde si tu tues cheptels et paysans en les forçant à vivre la nuit.

En terme technique, on peut imaginer des définitions locale du temps (solaire, Fuseau Berlin, Fuseau France) en fonction des activités dont les équivalences sont maintenus dans des fichiers de descriptions maintenues par des organismes à différentes échelles. Les pays garderaient leurs fuseaux et entretiendrait les fichiers de définitions des zones géographiques qu'il régi, et la ville dans le même format, le temps qu'elle choisit.

T'imagines : t'arrive à Toulouse, juste sous le panneau de la ville t'as 6 horloges : le temps pour si t'es un camionneur international, le temps à laquelle la poste ouvre, et le temps pour amener tes enfants à l'école ou faire des démarches à la mairie, et si tu veux le temps local des offices religieux et prières.

En terme politique ce serait un tsunami que l'état régalien accepte d'arrêter de nous casser les couilles à vouloir tout définir EXCLUSIVEMENT non seulement le TEMPS, mais aussi les VITESSES.

Le pot de pus de la réglementation sur les vitesses est démocratiquement du même tonneau empoisonné que celui du choix des vitesses sur la route.

Un choix arbitraire avec des choix impopulaires technocratiquement et indéniablement meilleurs en termes de coût en vies humaines. En fait, d'où suis je si sûr que les citoyens sont CONTRE la baisse des vitesses autorisées, j'en crois que mon accès aux tribunes sur lesquelles un biais de sélection social s'applique qui favorise les anti-baisses de vitesse.

Ce qu'on désigne comme populaire, ce sont des poujadistes, des favorisés qui se prétendent populos pour faire valoir leurs points de vue, mais tu les regardes, ils sont pas populos...

Nan, quand tu peux pas faire confiance aux tribunes publiques ou aux experts, tu délègues. Tu délègues aux villes, aux entreprises, aux administrations leurs choix d'horloges, et d'une décision qui a longtemps était exclusive de l'état tu en refais un lieu de discussion éclairés et non discriminatoire de décision qui impactent notre vie, parfois notre mort, et notre bien être. Vu que pour les vitesses on est loin barré dans un débat pourri, je propose qu'on fuit courageusement vers l'expression démocratique et tolérante de nos temps locaux auxquels les peuples acceptent de se soumettre.

Les conspirations n'existent pas est une théorie conspirationniste.

la conspiration de l'ordre morale consiste à nier l'existence des conspirations



Entente secrète entre plusieurs personnes, par exemple contre l’État et les pouvoirs publics, ou contre toute autre organisation.
-- wikidictionnaire

Union de plusieurs personnes mal intentionnées contre l'Estat ou les puissances, qui tâchent à le brouiller, ou à les destruire.
-- Vieux Larrousse
On est pas certain de savoir à qui les gens en veulent, mais une conspiration à minima c'est une entente secrète de plusieurs personnes en vue de porter atteinte à une organisation.

La presse passe son temps à parler de « théories conspirationistes », comme si la conspiration était une théorie fumeuse sans assisses. Pourant, la lutte contre les conspirations et leurs mises en évidence est un des cœurs de l'activité : il suffit de regarder les premières pages google pour constater que non seulement les conspirations de marchands pour le moins pour faire payer les consommateurs plus chers existent, mais sont prouvées, assises et condamnées.

On peut arguer du fait que les consommateurs ne sont pas une organisation, mais dans un contexte où la pauvreté s'accroit, une entente illégale sur les prix, en appauvrissant les peuples au profits d'entreprises souvent étrangères qui par ailleurs sont les personnes juridiques qui en volume représentent le gros de l'évasion fiscale, et de la fraude au taxe peut interroger.

Si l'Europe dévoile des conspirations non théoriques, mais réelles tout les jours, alors comment diantre peut on en arriver à déclarer l'existence de conspiration du domaine du fantasme théorique ?

De César à l'attentat du petit Clamart, la conspiration contre l'État par des membres de l'état est en outre avéré comme une constante historique de l'Histoire des Gaules.

L'existence d'une cabale, d'un complot, d'une conspiration de riches pour nuire à l'état est même grâce aux efforts de transparence bien documentée.

D'un coté, économiquement, on constate que des personnes dont le seul mérite est la naissance voient leurs patrimoines augmenter au détriment même des entrepreuneurs dont les revenus ne croissent pas aussi vites.

Si on veut se faire l'avocat des riches, force est de constater que si la richesse devait récompenser le mérite, un État va mieux quand il rémunère le risque des fourmis, en non le parasitisme des cigales. Parler de lutte des classes, quand dans une même classe il y a une divergence structurelle antagoniste dans la classe elle même me paraît l'idée la plus con du Marxisme. Surtout, que la richesse de l'entrepreneur est bonne pour le prolétaire. La vraie discussion entre communisme et libéralisme devrait être le curseur incitatif à la reproduction sociale ?

Tu vois, si je te mets un fils d'agriculteur dans une ferme, j'économise un paquet d'éducation difficile à transmettre. Un pays qui n'est pas capable de nourrir ça pue. La part de transmission acceptable est évidemment une logique non absolue mais relative à l'évolution de la société (prix des prêts, coût de l'éducation, efficience de la transmission conservatrice), toute personne voulant décider absolument par critère idéologique de la part de mérite reproductif doit être encouragée nie l'aspect le plus important d'une réforme : non de faire le bien absolument, mais mieux dans un cadre que l'on contrôle. Le contrôle passe par la mesure, la mesure par poser des questions simples avec un budget.

Il me semble évident que notre époque est biaisée vers TROP de poids sur la rémunération de la naissance. Le problème, c'est que je n'ai que des observations indirects de son aspect délétère. Je vais juste repousser ce que l'on appelle la tragédie des trois en Province.
Grand père est un entrepreuneur innovant et lance la boîte, fiston est un conservateur éduqué grace à Papa qui conserve (la boîte perd son aspect concurrentiel), le petit fils dilapide en gérant la boîte comme un artiste qui s'affranchit des règles.

Pour ce que je perçois comme une déviation de la norme, il faut qu'il y ait influence pour masquer l'évidence...

Quelle évidence ? Celle que notre société est basée sur la corruption.

La loi sur la transparence qui oblige les lobbyes à se déclarer semble un bon pas vers la transparence, non ?

Non, le statut pour l'influence est l'un des plus flous, avec un modèle bien mou qui pousserait n'importe quel enquêteur de journaux ou de la justice à perdre de nombreuses heures dans la « mort par 1000 coupures » propre à cette activité.
Tout est en open data, sauf le plus intéressant : la liste des lobbyistes actifs. Et en plus les champs ne sont pas normalisés, Mr. Jean Michel Andréotti peut s'appeler ANDREOTTI J.M. dans la case suivante. J'imagine que prendre 5 minutes pour bien enlever les chausses trappes courant en data mining était trop demandé à la HAPTV pour un sujet aussi badin.

M'enfin, évidemment que je brûle de regarder cette liste de 2904 entités de lobbying référencées et de faire un sociogramme en recoupant avec les clients.

Mais, bordel, je vais pas me lancer aujourd'hui.

Le simple FAIT que le lobbying ÉXISTE et donne le droit à des déductions fiscales devrait vous faire tiquer..

Imagine, je suis bookmaker ET arbitre dans un SPORT avec une liste de participant du sport auquel j'ai le droit de faire des cadeaux.

Tu peux le faire de manière transparente, ça reste pas brillant que les mêmes mecs qui peuvent fermer les bénéfices du pétrole à la Russie subventionnent par le crédit d'impôt du lobbbying les opérations d'influence de la Russie en Europe.

Je suis pas très patriote, mais même en dictature, donner de l'argent à quelqu'un qui se déclare TON ennemi pour t'influencer par une niche fiscale taillée sur mesure pour rendre la corruption des membres du parlement légale et documentée, ça me paraît très con. Au niveau Darwinisme des régimes d'état, je prédis que l'Union Européenne va pas durer longtemps, surtout si nos presses libres qui peuvent AVOIR ACCÈS publiquement aux registres des échanges légaux de corruptabilité respectable se bouchent le nez en criant : « à la théorie du complot ! Aucun état ennemi n'oserait acheter des encarts de pubs dans nos journaux pour nous influencer » !

Bref, je m'fous de vivtre en dictature rampante ou absurdisthan, en idéal soviétique, je demande juste que les crétins qui ont décidé de nous diriger ne chient pas la où ils mangent.

Je veux bien qu'ils peuvent déménager quand ils veulent, mais, leur richesse elle tient un peu au péquenot captif qui pait ses impôts. C'est pas Darwiniste de concevoir comme Naturel, protégé et rémunérateur de jouer contre son camps. En plus tu aides les corrompus et corrupteur en faisant des niches fiscales aventâgeuses pour les brebis galeuses.

Je me tâte pour savoir si c'est de l'incompétence crasse ou une volonté délibérée de nuire de la part plus souvent qu'au commun de fils de députés eux mêmes, mais ça se pose quand même là en idée pas foufou.

Je dis pas que le truc est branlant, je dis qu'en situation pas zoum zoum de conflit potentiel, on subventionne l'opération de désinformation Russe pendant que les députés disent qu'il faut plus de pognon pour lutter contre la désinformation... Les mêmes qui reçoivent du pognon des Russes...

Je dis pas qu'il y a une conspiration du silence pour ne pas parler de conspirations de nos élus contre l'état lui même : je me tais !