• Re: [gentoo-user] Writing more complicated scripts than I'm used too.

    From Sascha Spreitzer@21:1/5 to All on Sat Jun 14 10:50:01 2025
    Hi dale

    In shell scripting nowadays we define and reuse functions. Sections are no longer possible.

    I would recommend starting with beginners literature on «bash scripting» and to advance from there.
    A quick search brought up: https://linuxhandbook.com/bash/

    On 14 Jun 2025, at 05:44, Dale <[email protected]> wrote:


    […]

    In the old Basic days with Vic-20 puters, we had goto to
    move from one part of a program to another. No idea on bash tho.

    […]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bryan Gardiner@21:1/5 to Dale on Sat Jun 14 19:20:01 2025
    Hey Dale,

    On Fri, 13 Jun 2025 22:44:05 -0500
    Dale <[email protected]> wrote:

    Howdy,

    As most know, I ordered some books about writing scripts.  A couple
    things are not making sense to me.  Yet.  This is the basics of a
    script I want to write. 


    Section one.  See if a encrypted partition is open or not.  I use cryptsetup to open/close.
    If open, print that it is open then go to mount part of script in
    section two. 
    If not open, ask for pass phrase and confirm it is open.  Then go to
    section two.
    Section one done, or fi.

    Section two.  Is unencrypted file system mounted. 
    If mounted, print that it is mounted and exit. 
    If not mounted, mount and confirm mount and then exit.  If mount
    fails, print error. 
    Section two done, or fi. 

    Here's the thing I can't figure out.  Let's say the I need section one
    to go to section two at a certain point, maybe because the encrypted
    file system is already open as shown above, how do I tell it to skip
    to section two? 

    Shell doesn't have 'goto's, but there are many control structures
    available instead, the most important being ifs, loops (while, for),
    and functions to avoid repeating common code. So try to structure
    what you want in terms of those.

    In this case, what you wrote above already translates pretty much
    exactly to what you would need in a script. Something like:

    if <already open>; then # but replace "<already open>", see below
    # ...print already open...
    else
    # ...unlock the partition, check for error...
    fi

    if mountpoint -q /mnt/foo; then
    # ...print already mounted...
    else
    # ...mount, check for error...
    fi

    The 'if's already include skipping parts of the code you don't want to
    run; they just also enforce that execution continues downward :).

    Also, if something goes bad, how do I tell it to print out that
    something went wrong and stop? 

    echo "Error: Couldn't do X."
    exit 1

    Every program (e.g. your script) exits with a numeric code 0-255 for
    the calling program (e.g. the shell) to inspect. Convention is that 0
    means success and any non-zero number indicates some type of error
    (which is up to the program itself to decide, so you can pick
    whatever). So "exit [some nonzero number]" is how you stop and
    indicate failure. "exit 0" would indicate success.

    This error code is also how you can check for failure of cryptsetup
    and mount. If they return a zero code, great! If not, then we should
    abort.

    There are a few ways to write this. After each command, the shell
    sets a special variable "$?" to the command's exit code. So we could
    be explicit about it:

    cryptsetup open ...
    if [[ $? -ne 0 ]]; then
    echo "Error: Couldn't unlock disk."
    exit 1
    fi

    However, we can also write this more directly, because what 'if'
    *does* is check whether the command after the 'if' returns zero or not
    (and the '!' inverts the check to mean 'run if the command failed',
    rather than 'run if the command succeeded'):

    if ! cryptsetup open ...; then
    echo "Error: Couldn't unlock disk."
    exit 1
    fi

    You can repeat the "is it open" or "is it mounted" checks after the
    calls to cryptsetup or mount if you like, but typically one would just
    rely on the exit status.

    The book I'm reading is Linux command:  Advanced methods and
    strategies to shell scripting by William Vance.  I don't know who the
    guy is but it is the one with the newest copyright date.  2020.  It's basically the same info as all the other books which still has me
    clueless on the above info.  In the old Basic days with Vic-20
    puters, we had goto to move from one part of a program to another.
    No idea on bash tho. 

    Also, someone posted about mountpoint -q.  That will help with section two.  Is there a way to find out if a file system is open using
    cryptsetup or some other command that I can put in a script? 

    cryptsetup creates a symlink under /dev/mapper with the target name of
    the device you opened, so you could check for existence of that device
    (e.g. /dev/mapper/sda3_crypt or whatever it's called for you).

    if [[ -e /dev/mapper/sda3_crypt ]]; then

    Maybe this will get me started.  Then I get to write a lot of scripts
    for each drive or drive set.  o_O 

    Thanks. 

    Dale

    :-)  :-) 

    Hope this helps,
    Bryan

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Frank Steinmetzger@21:1/5 to All on Sun Jun 15 23:00:01 2025
    Am Fri, Jun 13, 2025 at 10:44:05PM -0500 schrieb Dale:
    Howdy,

    As most know, I ordered some books about writing scripts.  A couple
    things are not making sense to me.  Yet.  This is the basics of a script
    I want to write. 

    If you have a script with many sections that depend on one another, you can write it as one long script, or to make it more digestible when you read it
    a few years later, put blocks of code into functions and then call those functions from the main scope, like so:

    check_prereqs() {
    ...
    }

    do_stuff() {
    ...
    }

    cleanup() {
    ...
    }

    # main scope: call the above functions
    check_prereqs
    do_stuff
    cleanup


    To get flow control, it is common to have early return on error. That means: as soon as you encounter a problem that your script cannot handle, have the script exit. This is preferable over nested if-else-structures.

    You can take it to the extrem with the statement `set -e`. This causes the script to terminate as soon as any of its commands returns != 0 unhandled. That means if you want the script to continue, you need to “catch” any possible error case yourself with `if` or a || construct, as in:
    mountpoint /some/path || echo "/some/path is not a mountpoint."

    The disadvantage: the script becomes more verbose.
    The advantage: you might discover bugs that you never thought of and you
    make the script safer.


    Section one.  See if a encrypted partition is open or not.  I use cryptsetup to open/close.
    If open, print that it is open then go to mount part of script in
    section two. 

    Pseudo code for the first section:

    if check_container_is_open then
    print "container is open"
    else
    open_container
    if not check_container_is_open then
    print "Failed to open container."
    exit
    fi
    print "container is now open"
    fi

    Note that I did not put the last print into an else. Because if the script encountered the problem case, it would have exited anyways.


    If not open, ask for pass phrase and confirm it is open.  Then go to
    section two.
    Section one done, or fi.

    Section two.  Is unencrypted file system mounted. 
    If mounted, print that it is mounted and exit. 
    If not mounted, mount and confirm mount and then exit.  If mount fails, print error. 
    Section two done, or fi. 

    Here's the thing I can't figure out.  Let's say the I need section one
    to go to section two at a certain point, maybe because the encrypted
    file system is already open as shown above, how do I tell it to skip to section two? 

    As others mentioned, put the sections into functions, call the functions in sequence and let the functions return early if necessary.

    Also, if something goes bad, how do I tell it to print out that
    something went wrong and stop? 

    I tend to define a function called die in all my scripts that require an
    early exit on error:

    die() {
    print "$@" > /dev/stderr
    exit 1
    }

    Then, instead of a print, you simply put this into the script:
    die "LUKS container could not be opened."


    The book I'm reading is Linux command:  Advanced methods and strategies
    to shell scripting by William Vance.  I don't know who the guy is but it
    is the one with the newest copyright date.  2020.  It's basically the
    same info as all the other books which still has me clueless on the
    above info.  In the old Basic days with Vic-20 puters, we had goto to
    move from one part of a program to another.  No idea on bash tho. 

    Also, someone posted about mountpoint -q.  That will help with section two.  Is there a way to find out if a file system is open using
    cryptsetup or some other command that I can put in a script? 

    lsblk comes to mind. I guess it just reads internal data from /sys or /dev
    and puts it into a nice readable form.

    frank@q ~ lsblk
    NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
    loop0 7:0 0 102,9M 1 loop /mnt/data/audio/sid/hvsc/C64Music nvme0n1 259:0 0 1,8T 0 disk
    ├─nvme0n1p1 259:1 0 300M 0 part /boot
    ├─nvme0n1p2 259:2 0 16M 0 part
    ├─nvme0n1p3 259:3 0 195,2G 0 part /mnt/windows
    └─nvme0n1p4 259:4 0 1,6T 0 part
    └─root 253:0 0 1,6T 0 crypt
    ├─vg-root 253:1 0 50G 0 lvm /
    ├─vg-home 253:2 0 200G 0 lvm /home
    ├─vg-gentoo 253:3 0 50G 0 lvm /mnt/gentoo
    └─vg-data 253:4 0 1,3T 0 lvm /mnt/data

    To make parsing easier, you can define the colums to display yourself. Then only output type and mointpoints, grep for lines beginning with crypt (to
    not catch lines that have “crypt” in the mountpoint) and lastly grep for the
    mountpoint, if needed:

    lsblk --option-for-your-columns | grep ^crypt | grep "$YOUR_MOUNTPOINT"

    --
    Grüße | Greetings | Salut | Qapla’
    Please do not share anything from, with or about me on any social network.

    If I wanted to sit in a Mercedes Benz, I’d call for a taxi.

    -----BEGIN PGP SIGNATURE-----

    iQIzBAABCgAdFiEEVbE9o2D2lE5fhoVsizG+tUDUMMoFAmhPMscACgkQizG+tUDU MMoI4A//c2HOk8qX22x0InS0vTXDPzmH32wUbgx/4DF9M3SmM1rphnboXbq3fCOh 8V8Udq92kdrdEwO5O1vDwg68yV9XvYJeAzf5FuSarWmsDS44fBy+z0Mv42QHILCS 1A8XWE0qdREX7ptln6DmT5tZ6qrkXtp/6yb3zeux9bJoJD7Vfse/WhFEj5Xy31kb aeEYr5OAScWVmm+j2KJCBKfL1JPKpRJ0eTWwmqkDNJKqGyM+Qj5ZmRMp3nPiK0pY Hnb3ZYjsdTOIxj5djWf7oduHH6gXTOJWS8jFR3/i5FyXW/mo26ePskurIdiFB6Rs zbR662Al+tAzKWcHsHcWe5hOhpCFtxHrXxXL5N0q1Cu3a12XhJMBnOsLE1HzDPAy M1OIpWfmV0XkaERspI/NLg7pmHs+iyig2n1pT4ZFq1+COCW0930R5Fd/odOaK6Gg 8S13/UgjOMqh8oOc2lqVy55dYzWjsAEe3kI7U9GepS4ZGamfdQZZSVpvSs5LAMdn f4/AgoNThI1ibw1A27rLmuWfMWXKCvUU7t53ugYp/hNm6nueBKC4Khc1WQXxGxxJ s8gBQ393AM/csx9Qm25R7zj4FWYIdSsDVoADqWoCe2c3prwAAr46JPb354fCYt6J CIPEfGT6qQ8jRJEY2gQqTJacuG3uFReXyV5ORfOFuTBUUr4UzxA=
    =Q9bm
    -----END PGP SIG
  • From Frank Steinmetzger@21:1/5 to All on Wed Jul 2 02:30:01 2025
    Am Tue, Jul 01, 2025 at 06:50:40PM -0500 schrieb Dale:

    OK.  I got one wrote, sort of.
    […]
    This is the script.  Tell me what I did wrong.  Please be kind.  This is the first real script I've ever done. 

    I’ll share some of my bash wisdom. Some may be nitpicks, others a matter of personal taste.

    #/bin/bash


    # Define the mount point
    MOUNT_POINT="/home/dale/Desktop/Crypt"
    LVM_DEV="/dev/vg.crypt/crypt"

    lsblk -o NAME -o LABEL | grep ^crypt-open > /dev/null
    -------------------------------------------^^^^^^^^^^^^
    grep has a -q option to suppress output, no redirection necessary.


    if [ "$?" -eq "0" ] ; then
    The `if $?` part is actually kinda nicely readable, but you could of course also do a direct `if lsblk | grep; then`.

        echo "Crypt file system is open"

        else echo "Crypt is not open.  Please enter passphrase."
    ------^^^^^^^^^
    Lol, it never occured to me that `else` may be followed by a command without semicolon, because I’ve always written it on its own line. It is however common practice to put the else on the same level of indentation as its respective `if` and `fi`.

        cryptsetup open $LVM_DEV crypt
    fi



    # Check if the disk is already mounted
    if mountpoint -q "$MOUNT_POINT"; then
        echo "The disk is already mounted at $MOUNT_POINT."
        # mount if not mounted
        else mount $MOUNT_POINT
        exit 0
    fi

    Same thing here with the `else` indentation. It is not visible on first
    sight that there is an if/else/fi structure here. And it’s not immediately clear that the exit also belongs into the else block.


    This is simple still but hey, I'm new at this.  It does work on one part
    of it at least.  ROFL 

    Tool tip: shellcheck. It will give all sorts of feedback on common pitfalls and give suggestions on improvements. For instance, it showed me something I overlooked (you wrote #/bin/bash instead of #!/bin/bash).

    --
    Grüße | Greetings | Salut | Qapla’
    Please do not share anything from, with or about me on any social network.

    Electronically yours

    -----BEGIN PGP SIGNATURE-----

    iQIzBAABCgAdFiEEVbE9o2D2lE5fhoVsizG+tUDUMMoFAmhkfLQACgkQizG+tUDU MMow4A//dtuGI2E3UBb/YMb2AvKqMgGOd8PxeELNHi1x3KDFsUb9NRTjXTdjQtqK Ys5Ms2EEoXrWNoB/lxhRiaYyHZ5jAnVaaaLRk6WWtIq0iTYUuYa6d0TLp4r9k/94 iQCemwytB2xU/eJfxkBDX0mpGGXSoW6gK99LzH7O7GaxCWwP6vb7nskYrTF7sGVD dQSgAJZSV6sauBwrHVE6UFh2rk8+wOi3ArxdKWl1LmBCmZIdPHKsQkSVjB+uikHA 0epPUnTS3PgRAgPuAT2lWApkL81EnQmqq+XoRBzI9vF5ld/8MdzuQezkw6aeNf4N N6+SolgGjPLSdkYZt+y3SNJnxPb07e4x2kT4fYwY+ORmVz4xKx7pUE9MA510qFsm bRQTUe6xkmwu7lRNFo2z7yNvRV5IYsy6ppYazzhGBttCHJuHhBEAtZ0tJWrbWXIw OetElBpTpQZasIPLMnxAE90Nh9B+EUMa64suNkiVzQ9jbSwxhzpVuyhLkr8VT/a2 GRhp6Cklb/aeco0duNJj4sxP+50/lLdrBRiHmCSsQsihRxspJOnxMmbPq6U5lE0J rFQKmdPCdVTzKzMW4uM8D+z4dhDGwWK3myJtyuy4UYMM4T9N+ZAmVCqywmGtJmvv +7jFAsfkjz3Cpe5loDh1RPEaTz6+ik14tyb2oLML/Y67oLZ2MYo=
    =FVog
    -----END PGP SIGNATURE-----

    --- SoupGate-Win32 v1.05
  • From Eli Schwartz@21:1/5 to Dale on Wed Jul 2 03:20:01 2025
    This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --------------z32A9gUxrwyawlJqmEKOZc0D
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: quoted-printable

    On 7/1/25 8:47 PM, Dale wrote:

    Lol, it never occured to me that `else` may be followed by a command without
    semicolon, because I’ve always written it on its own line. It is however >> common practice to put the else on the same level of indentation as its
    respective `if` and `fi`.

    Well, this part of the script may not have been executed yet.  Keep in
    mind, the device is open and mounted so it only runs the first bit, I
    guess it ignores the rest.  I may be wrong tho.  Does it need to be on
    its own line?  I'm learning, trying to anyway.  May as well learn it right.  LOL 


    "else" doesn't need to be on its own line but people almost universally
    do so because it makes it easier to read.



    if [ "$?" -eq "0" ] ; then
    echo "Crypt file system is open"
    else
    echo "Crypt is not open. Please enter passphrase."
    cryptsetup open $LVM_DEV crypt
    fi


    This makes your eyes get drawn to the lines that are aligned left, which
    have the "when shall I run it?" logic. You can easily tell that
    "cryptsetup open" happens AFTER the "else".


    --
    Eli Schwartz

    --------------z32A9gUxrwyawlJqmEKOZc0D--

    -----BEGIN PGP SIGNATURE-----

    wnsEABYIACMWIQTnFNnmK0TPZHnXm3qEp9ErcA0vVwUCaGSG/AUDAAAAAAAKCRCEp9ErcA0vV7q8 AQCMqGMcjAJ5/GD7ALRSEkKunfvA/S0DZdao89DnoGsWIQD9FikWvR8vX+ojH8A0VPMFw9WQYcie 35BLQEibhKpIEQI=
    =3Bvb
    -----END PGP SIGNATURE-----

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)