• Basic script help

    From Avon@21:1/101 to All on Sun Aug 1 15:27:01 2021
    Hi all.

    I'm new to writing .sh scripts in Linux.

    What I want to do is run something at Agency so when new files land in my inbound a .sh script is run and tests are performed such that if it's a Galactic Dynasty file then the script runs GD maint, if it's a For Honour
    file it runs FH maint etc.. you get the idea.

    Could someone share the correct syntax for such a .sh and I can then puddle
    my way through making it work?

    With thanks, Paul.

    --- Mystic BBS v1.12 A46 2020/08/26 (Linux/64)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Zip@21:1/202 to Avon on Sun Aug 1 09:44:51 2021
    Hello Avon!

    On 01 Aug 2021, Avon said the following...
    What I want to do is run something at Agency so when new files land in my inbound a .sh script is run and tests are performed such that if it's a Galactic Dynasty file then the script runs GD maint, if it's a For Honour file it runs FH maint etc.. you get the idea.

    I think the 'find' command will come in handy here.

    Are there any specific filename patterns which can be detected for each of those?

    Just as an example, although pointing it at my *outbound*, because that's the only place where I have some status files lying around:

    if [ ! -z "$(find /mnt/bbs/echomail/out/ -xdev -type f -name '*.sts' -print -quit)" ]; then echo "Found something"; fi

    This will search for *.sts files under /mnt/bbs/echomail/out, and echo a string if it found some. That's where you would call your script(s).

    The directory/path *should* have a trailing slash as in the example to avoid symlink diversion (not very likely but anyway). And the -xdev is another safeguard against descending (probably by mistake, or by symlinks) into other file systems, which probably is not desired.

    The way this works is that 'find' will locate any matching file(s), print the name of the first one (only), and immediately quit after that. This results in a non-empty string as output, which 'if' checks for. And, if found, does something.

    The 'find' command can be fine-tuned a lot. E.g.:

    * "-iname" instead of "-name" for case-insensitive searches.
    * "-mindepth 1 -maxdepth 9" after "-xdev" to restrict to files inside that base directory and max 9-1=8 subdirectories down.
    * "-regextype egrep" after "-xdev" and replacing "-name" with something like "-regex '.*\/[^.]+\.(mo[0-9a-z]|MO[0-9A-Z]|tu[0-9a-z]|TU[0-9A-Z]|we[0-9a-z]|WE[0-9A-Z]
    |th[0-9a-z]|TH[0-9A-Z]|fr[0-9a-z]|FR[0-9A-Z]|sa[0-9a-z]|SA[0-9A-Z]|su[0-9a-z]|S U[0-9A-Z])$'" to use regular expressions for the filename (actually, the entire path to the file). The example would check for packet files with either (all) lowercase or (all) uppercase extensions.

    Hope this helps!

    Best regards
    Zip

    P.S.

    I think you could make your binkd run your find script after each session with something like this in binkd.cfg:

    exec "/path/to/your/find_script.sh" * *.*

    Hmm, if the files have known extensions then maybe you could let binkd call the appropriate maintenance scripts directly without using 'find' at all?

    exec "/path/to/your/fh_maint.sh" *.fh *.FH
    exec "/path/to/your/gd_maint.sh" *.gd *.GD

    D.S.

    --- Mystic BBS v1.12 A47 2021/07/31 (Linux/64)
    * Origin: Star Collision BBS, Uppsala, Sweden (21:1/202)
  • From Vorlon@21:1/195 to Avon on Sun Aug 1 19:21:58 2021

    Hello Avon!

    01 Aug 21 15:27, you wrote to all:

    What I want to do is run something at Agency so when new files land in
    my inbound a .sh script is run and tests are performed such that if
    it's a Galactic Dynasty file then the script runs GD maint, if it's a
    For Honour file it runs FH maint etc.. you get the idea.

    That's easy. Just something like this in your binkd.config will the trick.


    exec "/pathtoscript/maint.sh" /husky/inbound.sec/*.[gG][aA][lL]




    Vorlon


    --- GoldED+/LNX 1.1.5-b20180707
    * Origin: Dragon's Lair BBS, Telnet: dragon.vk3heg.net (21:1/195)
  • From Avon@21:1/101 to Zip on Fri Aug 6 17:40:46 2021
    On 01 Aug 2021 at 09:44a, Zip pondered and said...

    Are there any specific filename patterns which can be detected for each
    of those?

    Yes I want one script to run then check for *.GAL files and if found in my inbound then run the GD maint

    I'd like to add additional such tests to the script so it tests for *.FHR
    files and runs For Honour etc :)

    Thanks :)

    --- Mystic BBS v1.12 A46 2020/08/26 (Linux/64)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Avon@21:1/101 to Vorlon on Fri Aug 6 17:42:26 2021
    On 01 Aug 2021 at 07:21p, Vorlon pondered and said...

    That's easy. Just something like this in your binkd.config will the
    trick.


    exec "/pathtoscript/maint.sh" /husky/inbound.sec/*.[gG][aA][lL]

    If BinkD were getting the files, I agree, but in this case it's the Mystic BinkP server at Agency getting them from a BinkD system. So at the moment I have it so a sh file runs on each inbound toss and then I just want to sort
    the logic so it tests and runs correct door maint first before it then hands back to Mystic and Mystic starts running MUTIL to import messages etc.

    --- Mystic BBS v1.12 A46 2020/08/26 (Linux/64)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Zip@21:1/202 to Avon on Fri Aug 6 12:30:49 2021
    Hello Avon!

    On 06 Aug 2021, Avon said the following...
    Are there any specific filename patterns which can be detected for ea of those?

    Yes I want one script to run then check for *.GAL files and if found in
    my inbound then run the GD maint

    I'd like to add additional such tests to the script so it tests for *.FHR files and runs For Honour etc :)

    Then you could try something like this in your BBS user's crontab (crontab -e as the BBS user):

    SHELL=/bin/bash

    * * * * * if [ ! -z "$(find /mystic/echomail/in/ -xdev -type f -iname '*.gal' -print -quit)" ]; then /path/to/gal_maint.sh; fi

    * * * * * if [ ! -z "$(find /mystic/echomail/in/ -xdev -type f -iname '*.fhr' -print -quit)" ]; then /path/to/fhr_maint.sh; fi

    This would run the checks every minute.

    Or place it in the system-wide crontab directory, e.g. in a file /etc/cron.d/custom_bbs, but then you'll have to specify the username of the BBS user om each crontab line, too:

    SHELL=/bin/bash

    * * * * * bbs if [ ! -z "$(find /mystic/echomail/in/ -xdev -type f -iname '*.gal' -print -quit)" ]; then /path/to/gal_maint.sh; fi

    * * * * * bbs if [ ! -z "$(find /mystic/echomail/in/ -xdev -type f -iname '*.fhr' -print -quit)" ]; then /path/to/fhr_maint.sh; fi

    (Username "bbs" in the example.)

    If the scripts output anything (information or error messages), that will be sent to the "bbs" user's local mailbox, or forwarded (e.g. to an e-mail address) if there is one specified in /etc/aliases:

    bbs: some.email@somedomain.com

    If you edit /etc/aliases, make sure to run 'newaliases' afterwards to be on the safe side (that it catches the change).

    Oh, and the reason for SHELL= in the crontabs are that cron usually defaults to /bin/sh for the shell to run the *cron line* with, and on some systems /bin/sh nowadays point to /bin/dash, a different and simpler shell, so if you have some complex expressions on the cron line, it might barf...

    Your *scripts*, though, will execute their code with the shell specified on their first line (#!/bin/something, usually #!/bin/bash).

    Hope this helps!

    Best regards
    Zip

    --- Mystic BBS v1.12 A47 2021/08/05 (Linux/64)
    * Origin: Star Collision BBS, Uppsala, Sweden (21:1/202)
  • From Oli@21:3/102 to Avon on Fri Aug 6 12:32:26 2021
    Avon wrote (2021-08-06):

    On 01 Aug 2021 at 07:21p, Vorlon pondered and said...

    That's easy. Just something like this in your binkd.config will the
    trick.


    exec "/pathtoscript/maint.sh" /husky/inbound.sec/*.[gG][aA][lL]

    If BinkD were getting the files, I agree, but in this case it's the Mystic BinkP server at Agency getting them from a BinkD system. So at the moment
    I have it so a sh file runs on each inbound toss and then I just want to sort the logic so it tests and runs correct door maint first before it
    then hands back to Mystic and Mystic starts running MUTIL to import messages etc.


    in bash you could use something like this:

    if compgen -G "/ftn/something/*.GAL" > /dev/null; then
    echo "Some files exist."
    fi

    * Origin: . (21:3/102)
  • From Oli@21:3/102 to Avon on Fri Aug 6 13:44:07 2021
    Avon wrote (2021-08-06):

    Or use some sane scripting language like ooRexx ;)

    #! /usr/bin/rexx
    call SysFileTree "/srv/ftn/inbound/*", "files", "F"

    if files.0 > 0 then
    do
    "/bin/echo 'Hello World'"
    end

    ---
    * Origin: . (21:3/102)
  • From Vorlon@21:1/195 to Avon on Sat Aug 7 10:54:36 2021

    Hello Avon!

    06 Aug 21 17:42, you wrote to me:

    exec "/pathtoscript/maint.sh" /husky/inbound.sec/*.[gG][aA][lL]

    If BinkD were getting the files, I agree, but in this case it's the
    Mystic BinkP server at Agency getting them from a BinkD system. So at
    the moment I have it so a sh file runs on each inbound toss and then I just want to sort the logic so it tests and runs correct door maint
    first before it then hands back to Mystic and Mystic starts running
    MUTIL to import messages etc.

    The same process can be used.. just slightly different... You would need to create a mail
    processing script that mystic uses instead of having the commands in the event.


    if [ -f /inbound/*.GAL ]

    process the gal file(s)

    fi




    Vorlon


    --- GoldED+/LNX 1.1.5-b20180707
    * Origin: Dragon's Lair BBS, Telnet: dragon.vk3heg.net (21:1/195)
  • From Avon@21:1/101 to Vorlon on Sat Aug 7 15:16:00 2021
    On 07 Aug 2021 at 10:54a, Vorlon pondered and said...

    The same process can be used.. just slightly different... You would need to create a mail
    processing script that mystic uses instead of having the commands in the event.
    if [ -f /inbound/*.GAL ]

    process the gal file(s)

    fi

    Can I then add multiple lines in the same .sh and know all if statements will be tested on each occasion the .sh is run? Or does it end the .sh once it
    runs once and ends on a fi ?

    --- Mystic BBS v1.12 A46 2020/08/26 (Linux/64)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Avon@21:1/101 to Zip on Sat Aug 7 16:10:56 2021
    On 06 Aug 2021 at 12:30p, Zip pondered and said...

    Hello Avon!

    Thank you for this. I'm trying at moment to just script a basic .sh file to call from Mystic events

    #!/bin/bash
    # check for and process incoming door files if found
    cd /bbs/mystic/echomail/in

    if [ -f /bbs/mystic/echomail/in/*.GAL ]
    cd /bbs/doors/gd
    ./GalacticDynasty maintenance;

    fi

    but this errors.. says something like syntax error near unexpected token 'fi'

    --- Mystic BBS v1.12 A46 2020/08/26 (Linux/64)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From Oli@21:3/102 to Avon on Sat Aug 7 06:30:33 2021
    Avon wrote (2021-08-07):

    On 06 Aug 2021 at 12:30p, Zip pondered and said...

    Hello Avon!

    Thank you for this. I'm trying at moment to just script a basic .sh file
    to call from Mystic events

    #!/bin/bash
    # check for and process incoming door files if found
    cd /bbs/mystic/echomail/in

    if [ -f /bbs/mystic/echomail/in/*.GAL ]
    cd /bbs/doors/gd
    /GalacticDynasty maintenance;

    fi

    but this errors.. says something like syntax error near unexpected token 'fi'

    try this:

    if [ -f /bbs/mystic/echomail/in/*.GAL ];
    then
    cd /bbs/doors/gd
    /GalacticDynasty maintenance
    fi

    but it only works if there is never more than one *.GAL file. Two files or more:

    "line 1: [: 123.GAL: binary operator expected"

    ---
    * Origin: . (21:3/102)
  • From Zip@21:1/202 to Avon on Sat Aug 7 08:28:06 2021
    Hello Avon!

    On 07 Aug 2021, Avon said the following...
    #!/bin/bash
    # check for and process incoming door files if found
    cd /bbs/mystic/echomail/in

    if [ -f /bbs/mystic/echomail/in/*.GAL ]
    cd /bbs/doors/gd
    ./GalacticDynasty maintenance;
    fi

    Ah, you have a missing "then" after the if.

    But you cannot use the wildcard expansion to check for files; -f expects exactly one argument and the wildcard might expand to none or multiple
    files...

    I can think of two approaches:

    #!/bin/bash
    if [ ! -z "$(find /bbs/mystic/echomail/in/ -xdev -mindepth 1 -maxdepth 1 -type f -iname '*.GAL' -print -quit)" ]
    then
    cd /bbs/doors/gd || { echo "ERROR: Could not switch to GD directory! " >&2; exit 1; }
    ./GalacticDynasty maintenance
    fi

    It checks for those files, case insensitive, exactly in /bbs/mystic/echomail/in (not in subdirectories!), and produces a full path to (only) the first such file it finds. This satisfies the if, which calls maintenance.

    Or:

    #!/bin/bash
    for f in /bbs/mystic/echomail/in/*.[gG][aA][lL]
    do
    [ -e "$f" ] || break
    cd /bbs/doors/gd || { echo "ERROR: Could not switch to GD directory! " >&2; exit 1; }
    ./GalacticDynasty maintenance
    break
    fi

    This one uses a peculiarity with the filename globbing of the shell.
    If the wildcard matches no files, $f will be the verbatim string "/bbs/mystic/echomail/in/*.[gG][aA][lL]", which should never match any file on disk.

    Inside the for loop, we check if the "current" file exists or not. If not, there were no matches at all, and we break the for loop and do nothing. Otherwise, we perform maintenance, and break the for loop after the first round (no need to run maintenance for each file).

    Hope this helps!

    Best regards
    Zip

    --- Mystic BBS v1.12 A47 2021/08/05 (Linux/64)
    * Origin: Star Collision BBS, Uppsala, Sweden (21:1/202)
  • From Vorlon@21:1/195 to Avon on Sat Aug 7 17:16:40 2021

    Hello Avon!

    07 Aug 21 15:16, you wrote to me:

    instead of having the commands in the event.
    if [ -f /inbound/*.GAL ]

    process the gal file(s)

    fi

    Can I then add multiple lines in the same .sh and know all if
    statements will be tested on each occasion the .sh is run? Or does it
    end the .sh once it runs once and ends on a fi ?

    My bad. I forgot the 'then' on the line after the if statement.
    Oli/Zip have given you further help.

    Try both option's from zip and choose the one you like the most. #-)




    Vorlon


    --- GoldED+/LNX 1.1.5-b20180707
    * Origin: Dragon's Lair BBS, Telnet: dragon.vk3heg.net (21:1/195)
  • From hyjinx@21:1/126 to Avon on Mon Aug 9 18:12:02 2021
    Hi Avon,

    Ah, you have a missing "then" after the if.


    Just in case you need some local timezone support, I'm happy to help you out with bash scripting if needs be. I'm an old-time Linux sysadmin from years
    ago, but shell scripting is like riding a bike (I only fall off every now and then!)

    Cheers,
    Al


    hyjinx // Alistair Ross
    Author of 'Back to the BBS' Documentary: https://bit.ly/3tRINeL (YouTube) alsgeeklab.com

    --- Mystic BBS v1.12 A46 2020/08/26 (Linux/64)
    * Origin: Al's Geek Lab -=- bbs.alsgeeklab.com:2323 (21:1/126)
  • From Avon@21:1/101 to hyjinx on Tue Aug 10 09:05:36 2021
    On 09 Aug 2021 at 06:12p, hyjinx pondered and said...

    Just in case you need some local timezone support, I'm happy to help you out with bash scripting if needs be. I'm an old-time Linux sysadmin from years ago, but shell scripting is like riding a bike (I only fall off every now and then!)

    Thanks Al.

    It's new for me as I've been using .bat files for many years... :)

    --- Mystic BBS v1.12 A46 2020/08/26 (Linux/64)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From paulie420@21:2/150 to Avon on Tue Aug 10 14:55:14 2021
    Thanks Al.

    It's new for me as I've been using .bat files for many years... :)

    Its been really nice seeing everyone jump in and help with both suggestions and examples to help you dive into bash scripting.

    Just another reason why FSX is the place to be. :P No response needed, I'm just proud of our community.



    |07p|15AULIE|1142|07o
    |08.........

    --- Mystic BBS v1.12 A47 2021/08/08 (Raspberry Pi/32)
    * Origin: 2o fOr beeRS bbs>>>20ForBeers.com:1337 (21:2/150)
  • From Avon@21:1/101 to Zip on Sat Aug 14 14:31:09 2021
    On 07 Aug 2021 at 08:28a, Zip pondered and said...

    #!/bin/bash
    if [ ! -z "$(find /bbs/mystic/echomail/in/ -xdev -mindepth 1 -maxdepth 1 -type f -iname '*.GAL' -print -quit)" ]
    then
    cd /bbs/doors/gd || { echo "ERROR: Could not switch to GD directory! " >&2; exit 1; }
    ./GalacticDynasty maintenance
    fi

    thanks this is working :)

    I have been letting it run on auto pilot the last few days and run as a
    .sh each time an incoming packets is detected by mystic.

    If I were to add a similar section to the same .sh but get it testing for For Honour packets can I do that without issue? In a bat file after one section
    of the .bat is executed it may move to the :done section and exit so just checking if I need multiple .sh or ?

    --- Mystic BBS v1.12 A46 2020/08/26 (Linux/64)
    * Origin: Agency BBS | Dunedin, New Zealand | agency.bbs.nz (21:1/101)
  • From hyjinx@21:1/126 to Avon on Sat Aug 14 17:24:50 2021
    You can use functions in bash scripts, much more powerful, yet easy to use

    you simply define them at the start of the script as so:

    #!/bin/bash

    functionname() {
    things
    }

    and you call it with the name of the function wherever you like in the script as follows:

    functionname $VAR1 $VAR2

    if you want to pass it any variables, that is.

    Note that inbuilt vars $1 and $2 etc are the first and second command-line
    arg, so you can also make your script do interesting things depending upon
    what arguments you call... eg suppose you have a script called arg.sh:

    #!/bin/bash

    if [ -z $1 ]
    then
    echo "Your first command was $1"
    else
    echo "You didn't enter an argument on the command line. Bye"
    fi

    if [ $1 = "foo" ]
    echo "Ah, I see that $1 was foo. Wonderful!"
    fi

    if you run it at the cmldine you get:

    $./arg.sh foo

    you'll get two lines of output - saying your first command was foo, then the second echo. Anyway, you get the drift. Hope this helps.

    Al.


    hyjinx // Alistair Ross
    Author of 'Back to the BBS' Documentary: https://bit.ly/3tRINeL (YouTube) alsgeeklab.com

    --- Mystic BBS v1.12 A46 2020/08/26 (Linux/64)
    * Origin: Al's Geek Lab -=- bbs.alsgeeklab.com:2323 (21:1/126)
  • From Zip@21:1/202 to Avon on Sat Aug 14 10:24:55 2021
    Hello Avon!

    On 14 Aug 2021, Avon said the following...
    thanks this is working :)

    You're very welcome!

    I have been letting it run on auto pilot the last few days and run as a .sh each time an incoming packets is detected by mystic.

    Sounds great!

    If I were to add a similar section to the same .sh but get it testing
    for For Honour packets can I do that without issue? In a bat file after one section of the .bat is executed it may move to the :done section and exit so just checking if I need multiple .sh or ?

    There are no goto labels in shell scripts, but you can add another block of "checks/actions" (the entire if clause) after the first one, for FH.

    You will have to decide how to handle errors from each block, though. Should the second block run if the first one failed? (Probably.)

    Although cron will not care about exit status (but will report stdout and stderr output messages to you via mail), you might want to "collect" the status anyway and exit with status 0 (OK) if all was OK, and something not 0 if anything went wrong, for good measure.

    Something like:

    #!/bin/bash

    ERRORS_DETECTED=0

    if [ ! -z "$(find /bbs/mystic/echomail/in/ -xdev -mindepth 1 -maxdept -type f -iname '*.GAL' -print -quit)" ]
    then
    cd /bbs/doors/gd
    if [ $? -eq 0 ]
    then
    ./GalacticDynasty maintenance
    RC=$?
    if [ $RC -ne 0 ]
    then
    echo "ERROR: Non-zero exit code ($RC) from GD maintenance! " >&2
    ERRORS_DETECTED=1
    fi
    else
    echo "ERROR: Could not switch to GD directory! " >&2
    ERRORS_DETECTED=1
    fi
    fi

    if [ ! -z "$(find /bbs/mystic/echomail/in/ -xdev -mindepth 1 -maxdept -type f -iname '*.FHR' -print -quit)" ]
    then
    cd /bbs/doors/fh
    if [ $? -eq 0 ]
    then
    ./ForHonour maintenance
    RC=$?
    if [ $RC -ne 0 ]
    then
    echo "ERROR: Non-zero exit code ($RC) from FH maintenance! " >&2
    ERRORS_DETECTED=1
    fi
    else
    echo "ERROR: Could not switch to FH directory! " >&2
    ERRORS_DETECTED=1
    fi
    fi

    if [ $ERRORS_DETECTED -ne 0 ]
    then
    echo "ERROR: One or more errors detected! " >&2
    exit 1
    fi

    exit 0

    If you were wondering about the space after ! in the echo statements, ! is some kind of event/histort operator and bash will try to find an event named like whatever non-whitespace that follows !, and adding a space after ! solves this. Should only make a difference when copying and pasting things to the command line, though... But doesn't hurt even in the scripts. (Apart from that you get that extra space in the output.)

    Hope this helps. :)

    Best regards
    Zip

    --- Mystic BBS v1.12 A47 2021/08/08 (Linux/64)
    * Origin: Star Collision BBS, Uppsala, Sweden (21:1/202)