Announcement

Collapse
No announcement yet.

Some scripting tips...

Collapse
This topic is closed.
X
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Some scripting tips...

    Just a few tips.

    Bash is more fully featured than present day "barebones" shells. Debian "dash" seems to be even poorer than Busybox "ash", but not in all ways.

    In Bash you have access to two different ways to do arithmetic. You can do $(( a+1 )) or $[ a + 1 ]. The first will work in all shells. But $(( a++ )) will only work in Bash and Ash.

    Bash also has (( a++ )) without $. This will not output any number, but only update variables. Will not work in other shells. In all shells you can do:

    Code:
    : $(( a = a + 1 ))
    The ":" is a synonym for "true" so the arithmetic behind it will get executed but it will not output anything. This last example is the only "safe" way because Dash does not support "a++" or equivalents.

    A busybox system may not have "mkfifo" but you can use mknod <name> p to make named pipes.

    When you create child processes from the shell, their process ID is going to be in "$!" but only for the last process. If you start a pipe, ie. tar + gz in a pipe (tar .... | gzip -1 > out) then you will not get tar process this way, but gzip process.

    If you make named pipe, you can get both:

    Code:
    tempdir=$(mktemp -d)
    mknod $tempdir/pipe p
    tar ..... > $tempdir/pipe &
    tarpid=$!
    gzip .... < $tempdir/pipe > out &
    gzippid=$!
    Then if you need to shut tar down, or request process updates, you can target it:

    Code:
    kill -USR1 $tarpid
    after

    Code:
    tar --totals=USR1
    This way you can have tar output stuff to a log file:

    tar 2> $tempdir/log

    and then read with tail:

    tail -f $tempdir/log

    or just read the last line:

    tail -1 $tempdir/log

    And parse it.



    If you want to read the last lines of a log file since you previously read it, you can use program logtail:

    apt show logtail

    Description: Print log file lines that have not been read

    Manual page is clearer:
    logtail2 reads a specified file (usually a log file) and writes to the standard output that part of it which has not been read by previous runs of logtail2. It prints the appropriate number of bytes from the end of logfile, assuming that all changes that are made to it are to add new characters to it.

    You could use it to periodically check for messages from log files. The program saves offsets in a file you can specify.


    You probably already knew, but reading data into variables is hard if you don't use files:

    echo "a b c d" | read q r
    > you might expect q to be "a" and r to be "b c d" but it won't work. Read was executed in subshell and does not pass variables to main shell.

    From file it is easy:
    read q r < file

    Bash has here text:
    read q r <<< $text

    But all shells have here doc:
    read q r << EOF
    $variable
    EOF

    This way, you can put a variable in a special inline document. The variable will get substituted for its contents. Now you can still read into variables (multiples) without creating an actual file.

    EOF must be on single line, first character (no space).

    If you have to parse multiple fields from file, ie. fields 13, 14, 15, you can use awk to first print them:

    result=$( cat file | awk '{print $13 " " $14 " " $15) )
    now you can read them with here doc:
    read a b c << EOF
    $result
    EOF

    Some people say never to use cat:
    result=$( awk '....' < file )

    but I don't like it so much. Not me, me not. In Bash you can redirect the output of a process:

    awk '....' < <(other command)

    now you won't have any exit status of other command, but you will have ability to set shell variables, because awk is not running in a subshell, the other program is.

    It's like a pipe in reverse.

    Hope this helps a bit. Regards.
Working...
X