<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.3">Jekyll</generator><link href="https://smoser.github.io//feed.xml" rel="self" type="application/atom+xml" /><link href="https://smoser.github.io//" rel="alternate" type="text/html" /><updated>2023-07-21T20:46:45+00:00</updated><id>https://smoser.github.io//feed.xml</id><title type="html">smoser’s thoughts</title><subtitle>A dumping ground for thoughts and writings by smoser.</subtitle><author><name>Scott Moser</name></author><entry><title type="html">Today I learned: set -e sucks even more.</title><link href="https://smoser.github.io//2023/04/27/set-e-bad.html" rel="alternate" type="text/html" title="Today I learned: set -e sucks even more." /><published>2023-04-27T00:00:00+00:00</published><updated>2023-04-27T00:00:00+00:00</updated><id>https://smoser.github.io//2023/04/27/set-e-bad</id><content type="html" xml:base="https://smoser.github.io//2023/04/27/set-e-bad.html">&lt;h1 id=&quot;today-i-learned-set--e-sucks-even-more&quot;&gt;Today I learned: set -e sucks even more.&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Summary: Just don’t use set -e.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’ve never been a fan “errexit” in shell.  You’ve probably seen this as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set -e&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set -o errexit&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sh -e&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;People write lists of shell commands in a file and want the script to exit on the first one that fails rather than barreling on and causing damage.  That seems sane.&lt;/p&gt;

&lt;p&gt;I’ve always strived to write “shell programs” rather than “shell scripts”.  The difference being that the program will clean up after itself and give sane error messages.  It won’t just exit when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkdir&lt;/code&gt; fails and leave the user to understand some message like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; mkdir: cannot create directory ‘/tmp/work/bcd’: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ve always felt that errexit makes “good error handling” in shell more difficult.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://manpages.ubuntu.com/manpages/jammy/en/man1/bash.1.html&quot;&gt;bash(1)&lt;/a&gt; man page has the following text:&lt;/p&gt;
&lt;blockquote&gt;

  &lt;p&gt;If  a  compound  command or shell function executes in a context where -e is being ignored, none of the commands executed within the compound command or function body will be affected by the -e setting, even if -e is set and a command returns a failure status.  If a compound command or shell function sets -e while executing in a context where -e is ignored, that setting will not have any effect until the compound command or the command containing the function call completes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s an example of how painful it can be, and I took way too long today tracking down what was wrong.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;A Programmer starts off with a simple script &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make-lvs&lt;/code&gt; and uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set -e&lt;/code&gt;.&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;#!/bin/bash -ex
lvm lvcreate --size=1G myvg -n mylv0
lvm lvcreate --size=1G myvg -n mylv1
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;This looks fine for a “shell script”.  The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-x&lt;/code&gt; argument even makes shell write to standard error the commands it is running.  At this point everyone is happy.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Later the programmer looks at the script and realizes that he/she needs more flags to lvm lvcreate.  So now the script looks like:&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;#!/bin/bash -ex
lvm lvcreate --ignoremonitoring --yes --activate=y --setactivationskip=n --size=1G --name=mylv0 mylv0
lvm lvcreate --ignoremonitoring --yes --activate=y --setactivationskip=n --size=1G --name=mylv1 myvg 
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;I’m happy that the programmer here used long format flags as they are much more self documenting so readers don’t have to (as quickly) open up the &lt;a href=&quot;http://manpages.ubuntu.com/manpages/bionic/en/man8/lvcreate.8.html&quot;&gt;lvm man&lt;/a&gt; page.   It is easier to make sense of that than it is to read ‘&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvm lvcreate --ignoremonitoring -y -ay -ky -L1G -n mylv&lt;/code&gt;’.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;After doing so, they realize that they can make this look a lot nicer, and reduce the copy/paste code with a simple function wrapper.&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;#!/bin/bash -e
lvcreate() {
    echo &quot;Creating lv $2 on vg $1 of size $3&quot;
    lvm lvcreate &quot;--size=$3&quot; --ignoremonitoring --yes --activate=y \
        --setactivationskip=n --name=&quot;$2&quot; &quot;$1&quot;
    echo &quot;Created $1/$2&quot;
}

lvcreate myvg mylv0 1G
lvcreate myvg mylv1 1G
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;The improvements are great.  The complexity of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvm lvcreate&lt;/code&gt; is abstracted away nicely.  They’ve even dropped the vile &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set -x&lt;/code&gt; in favor of more human friendly messages.&lt;/p&gt;

    &lt;p&gt;Output of a failing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvm&lt;/code&gt; command looks like this:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ make-lvs; echo &quot;exited with $?&quot;
Creating lv mylv0 on vg myvg of size 1G
out of space
exited with 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The next improvement is where sanity goes completely out the window.  [&lt;em&gt;I realize you were questioning my sanity long ago due to my pursuit of shell scripting perfection&lt;/em&gt;].&lt;/p&gt;

    &lt;p&gt;The programmer tries to add reasonable ‘FATAL’ messages that you might find in log messages of other other programming languages.&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt; #!/bin/bash -e
 lvcreate() {
     echo &quot;Creating lv $2 on vg $1 of size $3&quot;
     lvm lvcreate &quot;--size=$3&quot; --ignoremonitoring --yes --activate=y \
         --setactivationskip=n --name=&quot;$2&quot; &quot;$1&quot;
     echo &quot;Created $1/$2&quot;
 }
 fail() { echo &quot;FATAL:&quot; &quot;$@&quot; 1&amp;gt;&amp;amp;2; exit 1; }
    
 lvcreate myvg mylv0 1G || fail &quot;Failed to create mylv0&quot;
    
 if ! lvcreate myvg mylv1 2G; then
     fail &quot;Failed to create lylv1&quot;
 fi
 echo &quot;Success&quot;
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;Can you guess what is going to happen here?&lt;/p&gt;

    &lt;p&gt;If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvm&lt;/code&gt; command fails (perhaps the vg is out of space) then the output of this script will look like:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; $ make-lvs; echo exited with $?
 Creating lv mylv1 on vg myvg of size 1G
 error: out of space
 Created myvg/mylv1
 Creating lv mylv2 on vg myvg of size 1G
 error: out of space
 Created myvg/mylv2
 Success
 exited with 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The attempt to handle the failure of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvcreate&lt;/code&gt; function with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;||&lt;/code&gt; on lines 10 and with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if !&lt;/code&gt; on line 12 made it a “compound command”.  A compound command disables the error handling and shell exit that would have come from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-e&lt;/code&gt; when the lvm command on line 4 failed.&lt;/p&gt;

&lt;p&gt;Above I’ve demonstrated with bash, but this is actually posix behavior, and you can just as well test the function with &lt;a href=&quot;http://manpages.ubuntu.com/manpages/bionic/en/man1/sh.1.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sh&lt;/code&gt;&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;Madness.&lt;/p&gt;

&lt;p&gt;If you’re interested in further reading, you can see this topic on the &lt;a href=&quot;https://mywiki.wooledge.org/BashFAQ/105&quot;&gt;BashFAQ&lt;/a&gt;.  I agree with GreyCat and geirha: “don’t use set -e. Add your own error checking instead.”&lt;/p&gt;

&lt;p&gt;If you’re &lt;em&gt;still&lt;/em&gt; here, the following is the version of the script that I’d like to see. Of course there are other improvements that can be made, but I’m happy with it.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;   #!/bin/bash
   info() { echo &quot;$@&quot; 1&amp;gt;&amp;amp;2; }
   stderr() { echo &quot;$@&quot; 1&amp;gt;&amp;amp;2; }
   fail() { stderr &quot;FATAL:&quot; &quot;$@&quot;; exit 1; }
   lvcreate() {
       local vg=&quot;$1&quot; lv=&quot;$2&quot; size=&quot;$3&quot;
       info &quot;Creating $vg/$lv size $size&quot;
       lvm lvcreate \
           --ignoremonitoring --yes --activate=y --setactivationskip=n \
           --size=&quot;$size&quot; --name=&quot;$lv&quot; &quot;$vg&quot; || {
               stderr &quot;failed ($?) to create $vg/$lv size $size&quot;
               return 1
           }
       info &quot;Created $vg/$lv&quot;
   }
   
   # demonstrate both 'command ||' and 'if ! command; then' styles.
   lvcreate myvg mylv0 1G || fail &quot;Failed to create mylv0&quot;
   
   if ! lvcreate myvg mylv1 1G; then
       fail &quot;Failed to create mylv1&quot;
   fi
   
   info &quot;Success&quot;
&lt;/code&gt;&lt;/pre&gt;</content><author><name>Scott Moser</name></author><category term="ubuntu" /><summary type="html">Today I learned: set -e sucks even more. Summary: Just don’t use set -e.</summary></entry><entry><title type="html">Fixing the qemu serial console terminal size.</title><link href="https://smoser.github.io//2023/03/21/qemu-serial-window-size.html" rel="alternate" type="text/html" title="Fixing the qemu serial console terminal size." /><published>2023-03-21T00:00:00+00:00</published><updated>2023-03-21T00:00:00+00:00</updated><id>https://smoser.github.io//2023/03/21/qemu-serial-window-size</id><content type="html" xml:base="https://smoser.github.io//2023/03/21/qemu-serial-window-size.html">&lt;h1 id=&quot;fixing-the-qemu-serial-console-terminal-size&quot;&gt;Fixing the qemu serial console terminal size.&lt;/h1&gt;
&lt;p&gt;Qemu can allow you to attach to a serial console of your guest.
This is done with either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-nographic&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-serial mon:stdio&lt;/code&gt;.
Its great for getting text output, but after you’ve logged in,
you may find issues editing long command lines or using an editor
such as vi.&lt;/p&gt;

&lt;p&gt;To fix this, you simply need to tell linux what the terminal
size you’re using is.&lt;/p&gt;

&lt;p&gt;First, figure out what your terminal size is.  You have to do this
before connecting to qemu, or some other way such as another tmux
window or terminal.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;With bash via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$LINES&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$COLUMNS&lt;/code&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; $ echo rows $LINES columns $COLUMNS
 rows 75 columns 120
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;With stty, look for ‘rows’ and ‘columns’ below:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; $ stty -a
 speed 38400 baud; rows 75; columns 120; line = 0;
 intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = &amp;lt;undef&amp;gt;;
 eol2 = &amp;lt;undef&amp;gt;; swtch = &amp;lt;undef&amp;gt;; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
 werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
 -parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
 -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
 -iuclc -ixany -imaxbel iutf8
 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
 isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
 echoctl echoke -flusho -extproc

 $ echo $TERM
 xterm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then tell linux inside qemu about it via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stty&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ stty rows 75 columns 120

# now show what it is
$ stty -a |head -n 1
speed 115200 baud; rows 75; columns 120; line = 0;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Last, you probably want to update your TERM variable :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ export TERM=xterm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Thats it.&lt;/p&gt;</content><author><name>Scott Moser</name></author><category term="ubuntu" /><summary type="html">Fixing the qemu serial console terminal size. Qemu can allow you to attach to a serial console of your guest. This is done with either -nographic or -serial mon:stdio. Its great for getting text output, but after you’ve logged in, you may find issues editing long command lines or using an editor such as vi.</summary></entry><entry><title type="html">Using network manager in an Ubuntu lxd container.</title><link href="https://smoser.github.io//2019/10/18/network-manager-ubuntu-lxd.html" rel="alternate" type="text/html" title="Using network manager in an Ubuntu lxd container." /><published>2019-10-18T00:00:00+00:00</published><updated>2019-10-18T00:00:00+00:00</updated><id>https://smoser.github.io//2019/10/18/network-manager-ubuntu-lxd</id><content type="html" xml:base="https://smoser.github.io//2019/10/18/network-manager-ubuntu-lxd.html">&lt;h1 id=&quot;using-network-manager-in-an-ubuntu-lxd-container&quot;&gt;Using network manager in an Ubuntu lxd container.&lt;/h1&gt;
&lt;p&gt;For one reason or another you may want to use NetworkManager inside a
container.  An lxd container of recent vintage Ubuntu release (18.04)
will have cloud-init render networking through systemd-networkd.&lt;/p&gt;

&lt;p&gt;I needed to play around with a vpn that expected NetworkManager to be
running.  Here is a simple recipe for setting up network manager to
manage network in an LXD container.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;create the container and then wait a bit for it to boot.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ lxc launch ubuntu-daily:18.04 nm-test
$ sleep 10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;disable cloud-init, remove cloud-init authored netplan config and install network manager.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ lxc exec nm-test -- touch /etc/cloud/cloud-init.disabled
$ lxc exec nm-test -- rm -f /etc/netplan/50-cloud-init.yaml
$ lxc exec nm-test -- apt-get --quiet update
$ lxc exec nm-test -- apt-get install --no-install-recommends --assume-yes network-manager
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Enable network manager to manage virtual ethernet devices [&lt;a href=&quot;https://bugs.launchpad.net/bugs/1676547&quot;&gt;bug 1676547&lt;/a&gt;] by creating an empty file to mask the distro-included version.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ lxc exec $name -- sh -c ': &amp;gt; /etc/NetworkManager/conf.d/10-globally-managed-devices.conf'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Restart network manager&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ lxc exec nm-test -- systemctl restart network-manager
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thats it.  You should have functional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nmcli&lt;/code&gt; now.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@nm-test:~# nmcli
eth0: connected to Wired connection 1
        &quot;eth0&quot;
        ethernet (veth), 00:16:3E:63:BC:31, sw, mtu 1500
        ip4 default, ip6 default
        inet4 10.157.246.65/24
        route4 0.0.0.0/0
        route4 10.157.246.0/24
        inet6 fd42:54b0:2d39:df1:5394:5920:e551:94d9/64
        inet6 fe80::d670:4eee:34ec:2dd9/64
        route6 fd42:54b0:2d39:df1::/64
        route6 ::/0
        route6 ff00::/8
        route6 fe80::/64
        route6 fe80::/64

lo: unmanaged
        &quot;lo&quot;
        loopback (unknown), 00:00:00:00:00:00, sw, mtu 65536

DNS configuration:
        servers: 10.157.246.1
        domains: lxd
        interface: eth0

        servers: fe80::fced:6bff:fe63:9e55 fd42:54b0:2d39:df1::1
        interface: eth0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It may be useful for you to rename the automatically generated ‘Wired Connection 1’ to something more friendly.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ lxc exec nm-test -- nmcli conn modify 'Wired connection 1' connection.id eth0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Lastly, you may not get the a dhcp request by default.  I’m not sure why, but I have seen that happen.  To tell network-manager that you want one:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ lxc exec nm-test -- nmcli conn modify eth0 ipv4.method auto
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Scott Moser</name></author><category term="ubuntu" /><summary type="html">Using network manager in an Ubuntu lxd container. For one reason or another you may want to use NetworkManager inside a container. An lxd container of recent vintage Ubuntu release (18.04) will have cloud-init render networking through systemd-networkd.</summary></entry></feed>