Author Topic: what would you use to replace Bash for scripting?  (Read 11262 times)

0 Members and 1 Guest are viewing this topic.

Offline bitwelder

  • Frequent Contributor
  • **
  • Posts: 966
  • Country: fi
Re: what would you use to replace Bash for scripting?
« Reply #25 on: March 21, 2023, 09:15:15 am »
Bash is good, but it's too error prone.

What would you use to replace it?
Well, first of all, what's your target? What range of *nix (only Linux or also other Unixes?) and what type of h/w (beefy server or small SBC) should your script run on? 
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3909
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #26 on: March 21, 2023, 09:35:35 am »
Well, first of all, what's your target? What range of *nix (only Linux or also other Unixes?)

only GNU/Linux, I have no plans for {net , open , free, ...}-BSD

and what type of h/w (beefy server or small SBC) should your script run on?

from embedded GNU/Linux SBC boards(1) to small (for today standards) GNU/Linux servers(2).

(1)
the worst in terms of resources: PPC40x@133Mhz, 32MB ram, 5Mbyte/sec storage
the best in terms of resources: ARM-A53@1100Mhz, 1GB ram, 20Mbyte/sec storage
(2)
the worst in terms of resources: MIPS32R2/BE@680Mhz, 128MB ram, 10Mbyte/sec storage
the best in terms of resources: Intel-CoreDuo2@2200Mhz, 8GB ram, 50Mbyte/sec storage


The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online shapirus

  • Super Contributor
  • ***
  • Posts: 1310
  • Country: ua
Re: what would you use to replace Bash for scripting?
« Reply #27 on: March 21, 2023, 10:01:58 am »
Now, the question is, WHY do you want to replace bash with anything? It makes zero sense to do it for boot scripts, since they are executed only once. In terms of performance, you generally need something faster only if the program is to be executed at least a few hundreds or thousands times per second.

In terms of convenience, yes, bash and other shell languages aren't particularly well suited for big and/or complex programs, but then the question has to be "what language should I use for a given task?" rather than what the thread title says.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4028
  • Country: nz
Re: what would you use to replace Bash for scripting?
« Reply #28 on: March 21, 2023, 12:49:43 pm »
Where perl falls down is if you want data structures more complex than a simple array or dictionary e.g. nested data structures, trees, graphs etc.
No. It's very powerful and simple once you get the concept and understand how the nested structures are actually organized.

I first user perl professionally to do system configuration and migration tasks at Unisys for the NZ Inland Revenue "Server Redeployment Project" in 1997, where old SunOS servers turned up at my desk each day, I upgraded the RAM and disks in them, installed and configured Solaris and other software, and shipped them back to their appropriate offices.

There have been few days since when I haven't used existing perl scripts or one-liners. I've written some very complex stuff in perl. I think I know how complicated data structures work in perl and it is AWFUL compared to Python, Ruby, Javascript, Lua, C, Java, or just about anything else.

Simple hashes of hashes of hashes etc and hierarchical things in general are fine. Generalised graphs are not. They are UG-leeee.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3909
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #29 on: March 21, 2023, 01:14:11 pm »
Now, the question is, WHY do you want to replace bash with anything? It makes zero sense to do it for boot scripts

For me, boot-bash-scripts are too error prone to maintain and adapt to different needs.
They are not even used once but rather on demand to stop, reconfigure, and reload a service.
Code: [Select]
/etc/system/init/wifi stop
...
/etc/system/init/wifi start

Also, I want to use *the same language* to write tools that I have to use on a daily basis.
Python-based tools (including "emerge" and a great part of OpenRC) are too CPU-and-ram-hungry.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3909
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #30 on: March 21, 2023, 01:30:54 pm »
+=dev-lang/lua
+=dev-lua/luafilesystem
+=dev-lang/ruby
+=app-shells/dsh #(distribuited shell, seems interesting for the cluster)
+=app-shells/dash

added in the profile list of the new stage{1,2,3,4} under cooking.
cooking time, on the cluster of five Mac-Mini-i2: 96 hours for { mips32le, ppc32be, hppa2/32bit-be }

next week I will try to learn and experiment with new dev-lang/*, and with the two new shells  ;D
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3909
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #31 on: March 21, 2023, 01:42:39 pm »
perl

yup, I have also to support dev-lang/perl (at least on the building machine, whose profile is in use on the squad of Mac-Mini-i2) because it's used by several linux kernel scripts.

To build the kernel linux, you need perl.
In older kernel 2.6.* perl scrips need a patch to be compatible with modern perl interpreters.
(I don't know about kernel 2.4.*)

I am with perl v5.30.3, I think I won't update, and I don't think I will push it onto target-stages, so, /usr/bin/perl5 and the rest of the package (plus tons of dependencies, perl has many on Gentoo) won't be included in the final rootfs, e.g. on my Japanese GNU/Linux PDA, unless strictly required by some application  :-//

It will also save precious space on the little built-in nand flash.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline gf

  • Super Contributor
  • ***
  • Posts: 1165
  • Country: de
Re: what would you use to replace Bash for scripting?
« Reply #32 on: March 21, 2023, 01:45:03 pm »
For me, boot-bash-scripts are too error prone to maintain and adapt to different needs.
They are not even used once but rather on demand to stop, reconfigure, and reload a service.

Take care of startup dependecies! Only limited functionality of the system may be available when rc scripts are executed during system startup. For instance, if /usr is not yet mounted when a particular script is executed, then the script can't use a language interpreter which resides in /usr, and it also can't invoke any tools residing in /usr. Many rc scripts are therefore limited to /bin/sh and only a couple of tools residing in /bin or /sbin.
 

Online shapirus

  • Super Contributor
  • ***
  • Posts: 1310
  • Country: ua
Re: what would you use to replace Bash for scripting?
« Reply #33 on: March 21, 2023, 02:02:18 pm »
There have been few days since when I haven't used existing perl scripts or one-liners. I've written some very complex stuff in perl. I think I know how complicated data structures work in perl and it is AWFUL compared to Python, Ruby, Javascript, Lua, C, Java, or just about anything else.

Simple hashes of hashes of hashes etc and hierarchical things in general are fine. Generalised graphs are not. They are UG-leeee.
Well I have had quite an extensive experience with perl, including writing big programs, too. It's a lovely language, exceptionally easy to understand and use, and this applies to its data structures too. Basically, they are as simple or as complex as the programmer makes them. The language doesn't really enforce anything.

Comparison with C is weird for me. In C, it may become really tedious, unless you involve libs that do all the low-level heavylifting.
 

Online shapirus

  • Super Contributor
  • ***
  • Posts: 1310
  • Country: ua
Re: what would you use to replace Bash for scripting?
« Reply #34 on: March 21, 2023, 02:05:37 pm »
For me, boot-bash-scripts are too error prone to maintain and adapt to different needs.
They are not even used once but rather on demand to stop, reconfigure, and reload a service.
Now I'm starting to smell a little bit of something being not quite right there, such as trying to solve a problem already solved.
Are you writing your own init scripts? Are you writing them for your own software?
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3909
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #35 on: March 21, 2023, 02:44:05 pm »
Are you writing your own init scripts?
Are you writing them for your own software?

I thought it was clear that I wrote my own init scripts and my own tools in bash and I want to use something different for the next gen.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3909
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #36 on: March 21, 2023, 03:04:42 pm »
Take care of startup dependecies!

yup, each bash module directly reports its needs
e.g. sshd depends on network

there is an engine, written in C and directly called by /sbin/init (it's a build-in thread), that elaborates all the modules and outputs (pipe) a list based on priority and dependency

Code: [Select]
rte
mount-rootfs
kernel-specific
kernel-modules-dep
mount-others
mount-swap
system-clean
memory-clean
clock-simple
machine-identify
hostname
hostname-server
machine-specific
wlan-mesh-batman
networking-bridge
networking-loopback
networking-gateway
networking-ipforwarding
networking-syn
networking-snort
env-shared-libraries
http-tini-server
sftp-server
ssh-server
tftp-server
iperf-server
hostname-discovery-server
ttyS-init
uart-init
crypto-init
(e.g. on my router)

then it invokes a scheduler (written in bash) that reads the list from the pipe, and launches all the services found in etc/system/init/* (modules there are written in bash), one by one, without competition.

It's very clean, faster than OpenRC, and simple. But ... I think it can be improved with scripts written in Lua.
As well as my patch-manager and all the other big and complex bash scripts can be improved if written in Lua.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline gf

  • Super Contributor
  • ***
  • Posts: 1165
  • Country: de
Re: what would you use to replace Bash for scripting?
« Reply #37 on: March 21, 2023, 04:57:54 pm »
Take care of startup dependecies!

yup, each bash module directly reports its needs
e.g. sshd depends on network

there is an engine, written in C and directly called by /sbin/init (it's a build-in thread), that elaborates all the modules and outputs (pipe) a list based on priority and dependency


What I mean is, if all scripts are written in (say) Lua, then you also need to have Lua (and its prerequisites) installed in the initramfs.
[ Fortunately, Lua is still pretty lightweighted, compared to Python, Perl, V8, and others. ]
 
The following users thanked this post: DiTBho

Offline ledtester

  • Super Contributor
  • ***
  • Posts: 3035
  • Country: us
Re: what would you use to replace Bash for scripting?
« Reply #38 on: March 21, 2023, 05:37:34 pm »
If you have to use bash or sh for scripting, have a look at ShellCheck:

https://www.shellcheck.net/

It's a linter for shell scripts and it can catch a lot of common problems.
 
The following users thanked this post: MarkL, DiTBho

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14445
  • Country: fr
Re: what would you use to replace Bash for scripting?
« Reply #39 on: March 22, 2023, 12:03:41 am »
Take care of startup dependecies!

yup, each bash module directly reports its needs
e.g. sshd depends on network

there is an engine, written in C and directly called by /sbin/init (it's a build-in thread), that elaborates all the modules and outputs (pipe) a list based on priority and dependency


What I mean is, if all scripts are written in (say) Lua, then you also need to have Lua (and its prerequisites) installed in the initramfs.
[ Fortunately, Lua is still pretty lightweighted, compared to Python, Perl, V8, and others. ]

Yep. Lua is very small. It's more or less about 300KB of binary code.
I have a "minimal" Python 3.10 "distribution". Takes about 370MB, so 3 orders of magnitude more. ;D
« Last Edit: March 22, 2023, 12:05:32 am by SiliconWizard »
 
The following users thanked this post: DiTBho

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6239
  • Country: fi
    • My home page and email address
Re: what would you use to replace Bash for scripting?
« Reply #40 on: March 22, 2023, 03:11:19 pm »
-> can override functions without a warning
Use
    function funcname () {
        ...body...
    }
    declare -rf funcname
and function funcname can be referenced and used, but not redefined.

Note that function and variable namespaces are separate: you can also have a variable funcname.  You may therefore wish to add
    declare -r funcname=funcname

-> no actual return value
Use the 'first argument specifies result variable name' pattern:
    function funcname () {
        [[ $# -ge 2 ]] || return 1
        declare -n retval="$1"
        shift 1
        ...body...
        retval=value-or-expression
    }
    declare -rf funcname
    declare -r funcname=funcname
and you can modify the named variable in the caller scope.  Granted, this isn't "return value" per se, but passing a variable by reference, allowing modifying the variable in the caller scope.

In Bash, and many other shells, the return value is always status; zero for success, nonzero values indicating errors.
Exit status itself is always accessible as $?

-> the number of arguments is not checked
Just like in C main(), you need to do it yourself.  $# is the number of positional parameters ($1, $2, ..., also ${1}, ${2}, ...), NOT including the function name itself ($0 or ${0}.  In the example before, the line
        [[ $# -ge 2 ]] || return 1
means that unless there are at least 2 positional parameters given, the function returns immediately with exit status 1.

-> arguments data-type is not checked
Not automatically, no.  Technically, all shell variables and environment variables are strings, so there are no data types.

You can always define a function that assigns the value of an integer expression to a variable, or returns nonzero if it is not possible.  For example, if you want to evaluate any integer expressions,
    function inteval () {
        [[ -n "$1" && $# -ge 2 ]] || return 2
        declare -n retval="$1"
        shift 1
        ( retval=$(($*)) ) 2>/dev/null || return 1
        retval=$(($*))
        return $?
    }
For example, inteval X 2*3+4 returns with success, with X=10.

To verify a specific variable or value is an representable integer,
    function isint () {
        [[ $# -eq 1 && $1 =~ ^[-+]?[0-9]+ ]] || return 1
        ( tmp=$(($1)) && [[ "$tmp" == "${1#+}" ]] ) 2>/dev/null || return 2
        return 0
    }
For example, isint -254 returns with success, but isint 0x254 with failure.
Similarly, a large enough integer in magnitude will overflow and therefore return with failure.

the integer data type is simulated by external tools
No, integer arithmetic is implemented within Bash itself, and is quite fast.  All assignments of form VAR=$((expression)) (or VAR=$[expression]) will either assign an integer value of the expression to VAR, or fail with an interpreter error.

I do prefer the $[expression] form over $((expression)), because there is a risk of confusing the latter with $( (statement) ), which is replaced with the output of statement.

It is true that Bash does not warn about integer arithmetic overflow.  If you try e.g.
    X=$[ 1208925819614629174706176 ]
then X will be assigned a zero, because the right hand evaluates to 280 which wraps to zero.  Then again, C behaves the same.

-> compare two numbers is ugly, and too error prone
Ugly is in the eye of the beholder.

As to error prone, not so, when one uses the -lt, -le, -eq, -ne, -ge, and -gt arithmetic comparison operators in [ expression and [[ expression ]] expressions.  <, <=, ==, !=, >=, and > are lexicographic comparisons in [[ expression ]], not arithmetic comparisons.  =~ is a POSIX extended regular expression (string) match operator.
« Last Edit: March 22, 2023, 07:31:12 pm by Nominal Animal »
 
The following users thanked this post: mwb1100, DiTBho

Offline mwb1100

  • Frequent Contributor
  • **
  • Posts: 529
  • Country: us
Re: what would you use to replace Bash for scripting?
« Reply #41 on: March 22, 2023, 05:01:15 pm »
@Nominal Animal:  a nice set of suggestions, especially the $[expression] syntax which I was unaware of.  I'll be trying it out to see if I like it better than $((expression)).  I'm guessing that I'll be sticking with $((expression)) because the [] brackets make my brain think of of arrays at first glance (not sure why that doesn't happen with if [ ... ]).  But I'll give it a go.
« Last Edit: March 22, 2023, 07:27:45 pm by mwb1100 »
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6239
  • Country: fi
    • My home page and email address
Re: what would you use to replace Bash for scripting?
« Reply #42 on: March 22, 2023, 08:02:24 pm »
@Nominal Animal:  a nice set of suggestions. especially the $[expression] syntax which I was unaware of.  I'll be trying it out to see if I like it better than $((expression)).  I'm guessing that I'll be sticking with $((expression)) because the [] brackets make my brain think of of arrays at first glance (not sure why that doesn't happen with if [ ... ]).  But I'll give it a go.
Bash developers do intend to eliminate $[expression] at some point, with $((expression)) the preferred way.  POSIX shell spec also uses the latter, so consider me in the wrong here.  (I also object to the standard backslash escape mechanisms, especially \\ as an escaped \.  I much prefer '\/' for '\', '\,' for '"', '\.' for ':', and so on.)



For Dash users:
  • Autoremoved temporary directory works:
        readonly Work="$(mktemp -d)" || exit 1
        trap "rm -rf '$Work'" EXIT

    Just like in Bash, the the directory to be removed is substituted from the variable at the time the trap is set (because of the outer double quotes), and not at the time the trap triggers.  This means that even if you omit readonly, doing e.g. Work="/" does not change anything: the original temporary directory is deleted regardless.
     
  • Default value assignment works:
        VAR="${VAR:-default}"
    If VAR is unset or empty, it will be set to default.
    Similarly, ${#VAR} is the length (number of bytes in the C locale) of the value of VAR, ${VAR%suffix} and ${VAR%%suffix} remove the shortest or the longest (shell/glob pattern) suffix, and ${VAR#prefix} and ${VAR##prefix} remove the shortest or longest (shell/glob pattern) prefix.
     
  • Arithmetic substitution via $((expression)) works.
    Variable names do not need to be preceded by $: $((x*y)) calculates the product of $x and $y, if both are integers.
     
  • Logical expressions use [ expression ] syntax (not (( expression ))).
    <, =, !=, and > are lexicographic/string comparison operators.
    For arithmetic comparisons, use -lt, -le, -eq, -ne, -ge, and -gt.
    The -n "string" (true if nonempty string) and -z "string" (true if empty string), as well as the various test utility file/directory flags are also supported.
     
  • Function definitions do not use a keyword, they start with the function name:
        funcname () {
            ...body...
        }
     
  • Function definitions cannot be made immutable.
        readonly funcname
    only sets the variable funcname readonly.  Function names are in a separate namespace, and at least I haven't found any way to make Dash spit out an error when trying to redefine an already defined function.
     
  • Variables are scoped.  Therefore, a function evalint that evaluates an arithmetic expression saving it in the variable named in the first positional parameter, can be written as
        evalint () {
            [ $# -ge 2 -a -n "$1" ] || return 2
            local name="$1"
            shift 1
            [ "$name" = "${name##*[^_0-9A-Za-z]}" ] || return 2
            local value="$*"
            ( value=$(($value)) ) 2>/dev/null || return 1
            value=$(($value))
            eval "$name=$value"
            return 0
        }
    which will return success ($? zero) if successful and variable set, false (nonzero $?) otherwise.
    Note that while the eval looks scary above, name has already verified to contain only underscores and alphanumerics, and value is an arithmetic result.  So, it is actually safe, barring internal Dash bugs.

    For example,
        evalint x 2*3+4
    will be successful and set x to 10, but
        evalint x 2.2+1
    will fail.
     
For what it is worth, Bash startup latency on my system is about 7 milliseconds, whereas Dash startup latency is just 4 milliseconds.  If you run both under strace, you'll see Dash does much less initial work.

So, my answer would be 'Dash'.  :D
« Last Edit: March 22, 2023, 08:08:16 pm by Nominal Animal »
 

Offline Junaid_raza

  • Contributor
  • !
  • Posts: 12
  • Country: us
Re: what would you use to replace Bash for scripting?
« Reply #43 on: March 22, 2023, 08:59:16 pm »
If you're looking for a shell scripting language that is less error-prone than Bash, but don't want to use a language like Python due to resource constraints, one option to consider is Fish (Friendly Interactive Shell). Fish is designed to be more user-friendly and less error-prone than Bash, with features like syntax highlighting and automatic suggestions. It's also more powerful than traditional Unix shells, and includes support for functions, variables, and other programming constructs.

Another option to consider is Zsh (Z Shell), which is similar to Bash but includes additional features like tab completion and spelling correction. Zsh is also highly customizable, with support for plugins and themes.
 

Offline Fred27

  • Supporter
  • ****
  • Posts: 726
  • Country: gb
    • Fred's blog
Re: what would you use to replace Bash for scripting?
« Reply #44 on: March 23, 2023, 07:51:54 pm »
Having worked with many languages over the last 20 years and havng had to use Lua professionally in the last year, I'd say "anything but Lua". If bash is working for you, then stick with that.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4028
  • Country: nz
Re: what would you use to replace Bash for scripting?
« Reply #45 on: March 23, 2023, 10:31:48 pm »
Having worked with many languages over the last 20 years and havng had to use Lua professionally in the last year, I'd say "anything but Lua". If bash is working for you, then stick with that.

Care to expand on that?
 
The following users thanked this post: SiliconWizard

Online DimitriP

  • Super Contributor
  • ***
  • Posts: 1300
  • Country: us
  • "Best practices" are best not practiced.© Dimitri
Re: what would you use to replace Bash for scripting?
« Reply #46 on: March 23, 2023, 11:08:04 pm »
Having worked with many languages over the last 20 years and havng had to use Lua professionally in the last year, I'd say "anything but Lua". If bash is working for you, then stick with that.

Your lack of non-revisionistic attitude is disconcerting :)
   If three 100  Ohm resistors are connected in parallel, and in series with a 200 Ohm resistor, how many resistors do you have? 
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5895
  • Country: es
Re: what would you use to replace Bash for scripting?
« Reply #47 on: March 24, 2023, 05:18:10 am »
Bash error-prone? You could say the same for each existing programming language.
Bash does its job fine, anywhere just write and run, I've made lots of complex bash scripts for Openwrt.

If you want top performance, C is the way to go, but for checking something every second it'll do just fine.
Use sleep command, otherwise it'll loop as fast as it cans, wasting cpu power.

It seems what you really need is to learn/practice it!
« Last Edit: April 04, 2023, 05:41:25 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3909
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #48 on: March 24, 2023, 09:38:24 am »
It seems what you really need is to learn/practice it!

Debugging Bash scripts with poor built-in debugging features? Well ... there are better hobbies  :D
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4028
  • Country: nz
Re: what would you use to replace Bash for scripting?
« Reply #49 on: March 24, 2023, 09:38:53 am »
Bah error-prone? You could say the same for each existing programming language.

Some kinds of programming languages are more problematic than others.

Those based on textual substitution, repeated parsing, levels of quoting of special characters etc are especially prone to programming errors and often security risks as a result.

These include most shell scripting languages, TCL, SQL code assembled at runtime rather than precompiled with variables bound at runtime, any language with "eval", and the C preprocessor.

While algorithms using text substitution have almost as long a history in formal computer science as lambda calculus and Turing machines, there is a reason why we don't usually use any of them as-is for modern programming.
 
The following users thanked this post: DiTBho


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf