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

0 Members and 2 Guests are viewing this topic.

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3801
  • Country: gb
what would you use to replace Bash for scripting?
« on: March 20, 2023, 10:12:14 am »
Bash is good, but it's too error prone.

What would you use to replace it?
(excluding big elephants like Python, which I like, but it consumes too many resources)

Php ... well, it looked a good idea, after 1 year, let me say: never again!
Lua? eLua?
...

Looking for something I can use to replace my startup system scripts (/etc/init.d/*), as well as my system scripts (in /usr/bin/), currently all written in Bash-scripting.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4003
  • Country: nz
Re: what would you use to replace Bash for scripting?
« Reply #1 on: March 20, 2023, 12:05:29 pm »
What is wrong with bash?

Perl was explicitly designed to be used instead of shell scripting. It's more or a real programming language, but with convenience features to let you use it almost like shell.

Ruby is also very good at replacing shell scripting, especially once you "require 'fileutils'", and has a lot more of the shell/perl spirit than Python does. And is just simply a better language than Python.

TCL suffers from the same problems arising from being based on text replacement as shell.

 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3801
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #2 on: March 20, 2023, 12:11:40 pm »
I know eLua (e="e"embedded) has been used in SONY Playstation video games, embedded into the game engine.
Some text editors come with eLua built-in. Used to provide advanced (and programmable) macros facilities.

I am tempted to open a branch, replacing all the boot-scripts with Lua scripts.

You say tcl ... umm interesting too  ;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: 3801
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #3 on: March 20, 2023, 12:28:50 pm »
What is wrong with bash?

functions are not actually functions
-> can override without a warning
-> no actual return value
-> the number of arguments is not checked
-> arguments data-type is not checked

the integer data type is simulated by external tools
-> compare two numbers is ugly, and too error prone



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: 3801
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #4 on: March 20, 2023, 12:31:01 pm »
Ruby is also very good at replacing shell scripting, especially once you "require 'fileutils'", and has a lot more of the shell/perl spirit than Python does. And is just simply a better language than Python.

seems *very* interesting.
I have to understand
- how fast it is
- how much ram it consumes

First, let learn its basic usage  :D
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline shapirus

  • Super Contributor
  • ***
  • Posts: 1179
  • Country: ua
Re: what would you use to replace Bash for scripting?
« Reply #5 on: March 20, 2023, 12:33:57 pm »
seems *very* interesting.
I have to understand
- how fast it is
- how much ram it consumes

First, let learn its basic usage  :D
Be careful, it's way too easy to fall in love with Ruby.
 
The following users thanked this post: DiTBho

Offline alm

  • Super Contributor
  • ***
  • Posts: 2841
  • Country: 00
Re: what would you use to replace Bash for scripting?
« Reply #6 on: March 20, 2023, 12:44:54 pm »
functions are not actually functions
-> can override without a warning
-> no actual return value
-> the number of arguments is not checked
-> arguments data-type is not checked

the integer data type is simulated by external tools
-> compare two numbers is ugly, and too error prone
Those may be arguments not to want to write shell scripts, but not to rewrite scripts that will probably have been tested for years or even decades on many systems.

I believe most modern systems don't actually use bash for init scripts, but something lighter weight like ash. Sure, the language is ugly, but there's a reason why it has been used for simple scripts for decades.

Perl and Ruby would be the obvious candidates in my mind, but I'm not so sure if they are much lighter than Python. If you want very low footprint, try Forth. It's used in some bootloaders.
 
The following users thanked this post: abeyer, DiTBho

Offline shapirus

  • Super Contributor
  • ***
  • Posts: 1179
  • Country: ua
Re: what would you use to replace Bash for scripting?
« Reply #7 on: March 20, 2023, 12:48:35 pm »
I'd be struggling to find a good reason to use anything but lightweight shell for boot scripts.

And that's usually not even bash -- for example, Debian has dash as its generic /bin/sh interpreter:

Code: [Select]
Description: POSIX-compliant shell
 The Debian Almquist Shell (dash) is a POSIX-compliant shell derived
 from ash.
 .
 Since it executes scripts faster than bash, and has fewer library
 dependencies (making it more robust against software or hardware
 failures), it is used as the default system shell on Debian systems.

It's also a good practice to avoid using bash-specific functionality in shell scripts. It makes them less portable.
 

Offline MarkL

  • Supporter
  • ****
  • Posts: 2120
  • Country: us
Re: what would you use to replace Bash for scripting?
« Reply #8 on: March 20, 2023, 01:46:01 pm »
In defense of bash on a couple of things...

...
-> no actual return value
There is a "return [n]" command which sets the exit status of a function.  It can be tested by the caller in-line as 0 or non-0 (just like an external program call), or you can test for a specific return value by using $? in a subsequent conditional.

Quote
-> the number of arguments is not checked
If you need to check it, $# is local to the function and returns the argument count.

Quote
the integer data type is simulated by external tools
-> compare two numbers is ugly, and too error prone
Not sure what you mean by external tools, but comparing numbers using (( ... )) is built-in and follows C arithmetic evaluation syntax.  It's pretty clean looking, IMO:

  x=5
  y=6

  (( x < y )) && echo hi

  # or if you prefer the longer form...

  if (( x < y )); then
    echo hi
  fi


However, to add to your other list items, it really bugs me that bash doesn't support floats after all these years.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3801
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #9 on: March 20, 2023, 02:02:37 pm »
Quote
-> the number of arguments is not checked
If you need to check it, $# is local to the function and returns the argument count.

Code: [Select]
function foo() how many arguments does it need?!? undefined
{
    local arg1="$1"
    local arg2="$2"
    local arg3="$3"
    local argn=$#
...
}

then somewhere ... even far from the define (e.g. "source /opt/scripts/your_script"), you invoke foo "1" "2" what is arg3?!? empty, and do you always check argn?!? also, what if you "swap" two args?!?


I partially fixed this problem with  "check_var", which invokes "panic" if a var is empty

Code: [Select]
function foo() how many arguments does it need?!? undefined
{
    local fid="foo" <------------- isn't there a feature that automatically reports the function name?
    local arg1="$1"
    local arg2="$2"
    local arg3="$3"
...
    check_var "arg1" "$arg1" "$fid"
    check_var "arg2" "$arg2" "$fid"
    check_var "arg3" "$arg3" "$fid"
...
}

Code: [Select]
foo "1" "2"
Code: [Select]
[!] panic
    in function foo var arg3 is empty
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: 3801
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #10 on: March 20, 2023, 02:20:08 pm »
Not sure what you mean by external tools, but comparing numbers using (( ... )) is built-in and follows C arithmetic evaluation syntax.
However, to add to your other list items, it really bugs me that bash doesn't support floats after all these years.

I wrote a patch manager to facilitate kernel hacking.
I needed to comparing { binutils, gcc } version withing a { min ... max } range
and ended writing these bash functions

Code: [Select]
module="profile/do/utils_ver"

# 2.6.15 -> 002006015
#    ver -> num
function ver_num_get()
{
    local fid="ver_num_get"
    local item="$1"
    local cmp1
    local cmp2

    check_var "item" "$item" "$module" "$fid"

    cmp1=$(echo "$item < 10"  | bc -l)
    cmp2=$(echo "$item < 100" | bc -l)

    if [ "$cmp1" == "1" ]
       then
           ans="00$item"
       else
           if [ "$cmp2" == "1" ]
           then
               ans="0$item"
           else
               ans="$item"
           fi
       fi
    # return ans
}

# ver x.y.z -> %03x%03y%03z
function ver_get()
{
    local fid="ver_get"
    local item="$1"
    local is_done
    local curr
    local ifam
    local isub
    local iver

    check_var "item" "$item" "$module" "$fid"

    iver=""
    curr="$item"
    is_done="false"
    while [ $is_done == "false" ]
          do
              ifam="`myfilename_deextendL $curr`"
              isub="`myfilename_getextL   $curr`"

              ver_num_get $ifam
              iver="$iver$ans"

              curr="$isub"
              if [ "*$curr" == "*" ]
                 then
                     is_done="true"
                 fi
          done
    ans="$iver"
    # return ans
}

function ver_is_ok()
{
   local fid="ver_is_ok"
   local ver_cur="$1"
   local ver_min="$2"
   local ver_max="$3"
   local cmp1
   local cmp2

    check_var "ver_cur" "$ver_cur" "$module" "$fid"
    check_var "ver_min" "$ver_min" "$module" "$fid"
    check_var "ver_max" "$ver_max" "$module" "$fid"

   # convert into xxx format
   ver_get "$ver_cur"
   ver_cur="$ans"

   ver_get "$ver_min"
   ver_min="$ans"

   ver_get "$ver_max"
   ver_max="$ans"

   # check check the range borders
   cmp1=$(echo "$ver_cur >= $ver_min" | bc -l)
   cmp2=$(echo "$ver_cur <= $ver_max" | bc -l)

   if [ "*$cmp1" != "*1" ] || [ "*$cmp2" != "*1" ]
      then
          ans="false"
      else
          ans="true"
      fi

   #return ans
}

external tools required:
{
portage@sys-devel/bc:bc,
overlay@app-utils/filename_utils:{myfilename_deextendL, myfilename_getextL}
}

I wrote the overlay@app-utils/filename_utils package because I missed something similar in bash scripting.




(yes, the coding style is like ~my-c
I am too "my-c" addicted  ;D )
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1714
  • Country: se
Re: what would you use to replace Bash for scripting?
« Reply #11 on: March 20, 2023, 03:55:10 pm »
Of course I would use one of the most cross platform scripting languages, with deep object orientation, very regular syntax, nice data structures and control flow primitives, auto completion, and mostly self-explaining commands.

I'm obviously talking about PowerShell.

(ducks and runs, but it's quite good TBH).
Nandemo wa shiranai wa yo, shitteru koto dake.
 
The following users thanked this post: gmb42, DiTBho

Offline MarkL

  • Supporter
  • ****
  • Posts: 2120
  • Country: us
Re: what would you use to replace Bash for scripting?
« Reply #12 on: March 20, 2023, 04:34:02 pm »
Code: [Select]
function foo() how many arguments does it need?!? undefined
{
    local fid="foo" <------------- isn't there a feature that automatically reports the function name?
    local arg1="$1"
    local arg2="$2"
    local arg3="$3"
...
    check_var "arg1" "$arg1" "$fid"
    check_var "arg2" "$arg2" "$fid"
    check_var "arg3" "$arg3" "$fid"
...
}

${FUNCNAME[0]} contains the name of the currently executing function.  The other indices [1], [2], etc. are all the function names in the call stack.
 
The following users thanked this post: DiTBho, rteodor

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3801
  • Country: gb
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline MarkL

  • Supporter
  • ****
  • Posts: 2120
  • Country: us
Re: what would you use to replace Bash for scripting?
« Reply #14 on: March 20, 2023, 05:34:46 pm »
Here's a short example without using external calls for comparing a three-part version number, with no more than 3 digits in each part.  It uses the same technique as yours by converting the version number to a big integer.  Bash is using 64-bit signed integers (at least on my system), so there is room in this method before it breaks.

You could also just do the comparisons for major, minor, and sub-minor separately, which would avoid the one-big-integer conversion problems.

Code: [Select]
#!/bin/bash

version_ok() {
  local ver_cur="${1:?ver_cur not set}"
  local ver_min="${2:?ver_min not set}"
  local ver_max="${3:?ver_max not set}"
  local ver_cur_int
  local ver_min_int
  local ver_max_int

  # extract 3 integer fields separated by ".", and convert
  # to one big integer.
  #
  [[ $ver_cur =~ ^([0-9]*)\.([0-9]*)\.([0-9]*)$ ]] || {
    echo "bad version format: $ver_cur" 1>&2
    exit 1
  }
  ver_cur_int=$(( ${BASH_REMATCH[1]}*1000000 +
                  ${BASH_REMATCH[2]}*1000 +
                  ${BASH_REMATCH[3]} ))
  echo debug: ver_cur_int $ver_cur_int 1>&2

  [[ $ver_min =~ ^([0-9]*)\.([0-9]*)\.([0-9]*)$ ]] || {
    echo "bad version format: $ver_min" 1>&2
    exit 1
  }
  ver_min_int=$(( ${BASH_REMATCH[1]}*1000000 +
                  ${BASH_REMATCH[2]}*1000 +
                  ${BASH_REMATCH[3]} ))
  echo debug: ver_min_int $ver_min_int 1>&2

  [[ $ver_max =~ ^([0-9]*)\.([0-9]*)\.([0-9]*)$ ]] || {
    echo "bad version format: $ver_max" 1>&2
    exit 1
  }
  ver_max_int=$(( ${BASH_REMATCH[1]}*1000000 +
                  ${BASH_REMATCH[2]}*1000 +
                  ${BASH_REMATCH[3]} ))
  echo debug: ver_max_int $ver_max_int 1>&1

  # check for out of range
  #
  (( ver_cur_int > ver_max_int )) && return -1
  (( ver_cur_int < ver_min_int )) && return -1

  # version is ok
  #
  return 0
}


if version_ok  2.5.6  1.2.3  2.8.9; then
  echo version is ok
else
  echo version is not ok
fi
exit


EDIT:  Oops, fixed the RE.  I forgot the "*" so the previous code would not accept more than one digit.  The dangers of posting code without thorough real-world testing.  It should probably also check that each result was not more than 999 since there is only 3 digits allocated in the big int.  But the idea was really just to show how some of the internal features of bash could be used.
« Last Edit: March 20, 2023, 08:15:10 pm by MarkL »
 
The following users thanked this post: DiTBho

Offline MarkL

  • Supporter
  • ****
  • Posts: 2120
  • Country: us
Re: what would you use to replace Bash for scripting?
« Reply #15 on: March 20, 2023, 08:16:00 pm »
Sorry, fixed a problem with the previous example.  See code and the EDIT comment.
 
The following users thanked this post: DiTBho

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14316
  • Country: fr
Re: what would you use to replace Bash for scripting?
« Reply #16 on: March 20, 2023, 08:46:50 pm »
Lua.
 
The following users thanked this post: DiTBho

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1714
  • Country: se
Re: what would you use to replace Bash for scripting?
« Reply #17 on: March 20, 2023, 09:07:01 pm »
PowerShell.

this one?  :o :o :o
Yes.
TBH, my comment was written with my tongue not firmly planted but definitely leaning a bit on my cheek.

All I have said about PS is, in fact, true, and I even forgot to add the MIT licensing!

As a scripting language it is quite powerful, in conjunction with the .NET Core framework.
Very verbose though, but that makes it less cryptic than others.

I'm not really an expert, I just use it from time to time to automate tasks.

As an example, here is a Wake on LAN cmdlet written in PS, once it's been Import-Module'd, it appears as any other command and responds to most standard options (e.g. -help, autocompletes -mac and -ip etc. etc.):
Code: [Select]
function Send-WOL {
    <#
  .SYNOPSIS
    Send a WOL packet to a broadcast address
  .PARAMETER mac
   The MAC address of the device that need to wake up
  .PARAMETER ip
   The IP address where the WOL packet will be sent to
  .EXAMPLE
   Send-WOL -mac 00:11:32:21:2D:11 -ip 192.168.8.255
#>

[CmdletBinding()]
param(
    [Parameter(Mandatory = $True, Position = 1)]
    [string]$mac,
    [string]$ip = "255.255.255.255",
    [int]$port = 9
)
$broadcast = [Net.IPAddress]::Parse($ip)
$computers = @{ redacted = "ff-ff-ff-ff-ff-ff"; missing = "ff-ff-00-00-00-00" }
if ($null -ne $computers[$mac]) {
    $mac=$computers[$mac]
}
$mac=(($mac.replace(":","")).replace("-","")).replace(".","")
$target=0,2,4,6,8,10 | % {[convert]::ToByte($mac.substring($_,2),16)}
$packet = (,[byte]255 * 6) + ($target * 16)
Write-Host 'Sending to MAC:' $mac ' IP:' $broadcast
$UDPclient = new-Object System.Net.Sockets.UdpClient
$UDPclient.Connect($broadcast,$port)
[void]$UDPclient.Send($packet, 102)

}

It does not use anything outside PS and .NET Core, and works the same on both Linux and Windows.

Say what you want about Microsoft, .NET bloat (Core is not excessively large), yadda yadda, but it's not that bad.
Of course, I quite doubt it'll work on many of your vintage and interesting machines - I would not venture in even trying a recompile.

Nandemo wa shiranai wa yo, shitteru koto dake.
 
The following users thanked this post: DiTBho

Offline mwb1100

  • Frequent Contributor
  • **
  • Posts: 529
  • Country: us
Re: what would you use to replace Bash for scripting?
« Reply #18 on: March 20, 2023, 10:42:01 pm »
I know you said "(excluding big elephants like Python, which I like, but it consumes too many resources)", but for non-bash scripting I generally use:

  - python
 
And more recently:
 
  - go (aka golang)

Either are much nicer than bash for scripts of any complexity and they are very good with portability between Windows and Linux.  As a portability side note about bash: I've found that the bash interpreter that can be optionally installed with Git for Windows works far better than I ever expected it to at running my Linux scripts.  I'd estimate that 80% or more of them run with no changes whatsoever.

Python has the long running irritant of v2 vs v3, but over the past year or more I've found it easy to pretty much ignore v2.
 
The following users thanked this post: DiTBho

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3801
  • Country: gb
Re: what would you use to replace Bash for scripting?
« Reply #19 on: March 20, 2023, 11:14:39 pm »
Python has the long running irritant of v2 vs v3, but over the past year or more I've found it easy to pretty much ignore v2.

yup, Gentoo Portage is based on Python
It has been a pain since 2005 for me  ;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: 4003
  • Country: nz
Re: what would you use to replace Bash for scripting?
« Reply #20 on: March 21, 2023, 12:35:45 am »
As for "how heavy" are various languages, interpreted as the time taken to start up and run a trivial script and quit, 100 times...

Just the results, in order by wall time:

Code: [Select]

 0.143s awk
 0.158s bash
 0.162s ksh
 0.278s zsh
 0.329s perl
 0.344s tcsh
 0.530s lua
 1.957s tcl
 2.519s emacs lisp
 3.009s python
 4.568s ruby
 4.979s javascript
15.207s C (compiled each time)

I'd rather use perl than tcl or any of the shells. It has proper syntax and variables and is not based on hairy text interpolation and re-parsing. It was explicitly designed to be a shell replacement for system admins. 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. The syntax can also be cryptic.

Lua is almost as fast starting up (and much much faster than python or ruby) and is better for writing "real" programs with data structures, OO code than perl. It has more conventional syntax. It doesn't have as much built in for doing system kinds of things but there is os.execute() and io.popen().

Emacs turns out to be surprisingly fast to start up, beating python, ruby, and javascript and surprisingly not far behind tcl. Lisp is a real programming language, suitable for writing very large programs if you're so inclined. The syntax is not for everyone, but personally I find it better than python.

Javascript (node.js) is not all that much slower to start up than python or ruby, has the most C-like syntax if you like that kind of thing, has a huge ecosystem of libraries (similar to python I guess), and so much time and money has been put into the v8 engine that if you want to write complex algorithms then it's by far the fastest language in the above list, coming close to C++ / Java / C#.

Tests run on an M1 Mac.

Details:

bash

Code: [Select]
Mac-mini:programs bruce$ time (for x in `seq 100`; do bash -c 'echo $((3*14))' >out;done)

real 0m0.158s
user 0m0.042s
sys 0m0.089s

tcsh

Code: [Select]
Mac-mini:programs bruce$ time (for x in `seq 100`; do tcsh -c '@ r = (3 * 14);echo $r' >out;done)

real 0m0.344s
user 0m0.068s
sys 0m0.188s

python

Code: [Select]
Mac-mini:programs bruce$ time (for x in `seq 100`; do python3.10 -c 'print(3*14)' >out;done)

real 0m3.009s
user 0m1.875s
sys 0m0.559s

perl

Code: [Select]
Mac-mini:programs bruce$ time (for x in `seq 100`; do perl -e 'print 3*14,"\n"' >out;done)

real 0m0.329s
user 0m0.076s
sys 0m0.140s

ruby

Code: [Select]
Mac-mini:programs bruce$ time (for x in `seq 100`; do ruby -e 'print 3*14,"\n"' >out;done)

real 0m4.568s
user 0m3.269s
sys 0m0.964s

awk

Code: [Select]
Mac-mini:programs bruce$ time (for x in `seq 100`; do awk 'BEGIN {print 3*14}' </dev/null >out;done)

real 0m0.143s
user 0m0.033s
sys 0m0.081s

lua

Code: [Select]
Mac-mini:programs bruce$ time (for x in `seq 100`; do lua -e 'print(3*14)' >out;done)

real 0m0.530s
user 0m0.176s
sys 0m0.150s

javascript

Code: [Select]
Mac-mini:programs bruce$ time (for x in `seq 100`; do node -e 'console.log(3*14)' >out;done)

real 0m4.979s
user 0m3.459s
sys 0m0.871s

tcl

Code: [Select]
Mac-mini:programs bruce$ time (for x in `seq 100`; do echo 'puts [expr 3*14]' | tclsh8.6 >out;done)

real 0m1.957s
user 0m1.057s
sys 0m0.383s

emacs

Code: [Select]
Mac-mini:programs bruce$ time (for x in `seq 100`; do emacs --batch --eval '(print (* 3 14))' >out;done)

real 0m2.519s
user 0m1.340s
sys 0m0.662s

C

Code: [Select]
Mac-mini:programs bruce$ time (for x in `seq 100`; do ((echo '#include <stdio.h>';echo 'int main(){printf("%d\n",3*14);}') | gcc -xc -;./a.out) >out;done)

real 0m15.207s
user 0m3.927s
sys 0m1.616s
« Last Edit: March 21, 2023, 12:37:16 am by brucehoult »
 
The following users thanked this post: edavid, bpiphany, DiTBho

Offline MarkL

  • Supporter
  • ****
  • Posts: 2120
  • Country: us
Re: what would you use to replace Bash for scripting?
« Reply #21 on: March 21, 2023, 01:47:55 am »
Interesting results.  You might also want to give tcc a try on your Mac-mini.

Tcc is an ANSI C compiler that is optimized for fast compilation and it can be used in the same style as bash, perl, and other interpreters by including the following at the top:

  #!/bin/tcc -run
  <your C program here...>

You don't need the intermediate step of generating an executable.

A quick comparison between gcc and tcc on my system:
Code: [Select]
piper$ time (for x in `seq 100`; do ((echo '#include <stdio.h>';echo 'int main(){printf("%d\n",3*14);}') | gcc -xc -;./a.out) >out;done)

real   0m2.536s
user   0m1.866s
sys    0m0.705s

Code: [Select]
piper$ time (for x in `seq 100`; do ((echo '#include <stdio.h>';echo 'int main(){printf("%d\n",3*14);}') | tcc -run -) >out;done)

real   0m0.223s
user   0m0.174s
sys    0m0.069s
 
The following users thanked this post: DiTBho, shapirus

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4003
  • Country: nz
Re: what would you use to replace Bash for scripting?
« Reply #22 on: March 21, 2023, 03:39:55 am »
Interesting results.  You might also want to give tcc a try on your Mac-mini.

tcc certainly looks a lot faster for this usage. Unfortunately HomeBrew informs me that "tcc: This formula either does not compile or function as expected on macOS versions newer than Catalina due to an upstream incompatibility."

If "newer than Catalina" includes Catalina, then it might be that tcc only generates 32 bit x86 code as Catalina was the first version to require x86_64 applications only.

Note that MacOS is very slow to run a newly-compiled application the first time, and so tcc might not make much difference. Note that only about 55ms out of the 152ms total time for each run is made up of system+user time, whereas with the others system+user add to something close to the real time.

I think the OS might well be calculating a fingerprint of the app and checking it against an internet database of malicious programs before running it the first time after it is compiled. If I 'cp a.out b.out' and then run the same test, compiling to a.out but then running the saved b.out then the time reduces from 15.2s to 4.4s (faster than ruby and javascript).

My RISC-V VisionFive 2 (with Ubuntu) runs the C test faster than the M1 Mac, in 13.7s, with system+user adding to 13.6. The b.out trick makes no difference at all. The perl and python tests (to pick just two) take just over twice as long as the Mac.
 
The following users thanked this post: DiTBho

Offline shapirus

  • Super Contributor
  • ***
  • Posts: 1179
  • Country: ua
Re: what would you use to replace Bash for scripting?
« Reply #23 on: March 21, 2023, 08:16:41 am »
It was explicitly designed to be a shell replacement for system admins.
No. It was designed as a script language aimed at processing text and generating reports. Never aimed to be a shell replacement, because the existing shells did their job very well at the time and there was no need to replace them.

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.

The syntax can also be cryptic.
Only if you want it to.


p.s. bash vs dash (64-bit x86 linux):

Code: [Select]
$ time (for x in `seq 1000`; do bash -c 'echo $((3*14))' >out;done)

real    0m1.177s
user    0m0.830s
sys     0m0.388s


$ time (for x in `seq 1000`; do dash -c 'echo $((3*14))' >out;done)

real    0m0.707s
user    0m0.462s
sys     0m0.287s
« Last Edit: March 21, 2023, 08:21:06 am by shapirus »
 
The following users thanked this post: DiTBho

Offline shapirus

  • Super Contributor
  • ***
  • Posts: 1179
  • Country: ua
Re: what would you use to replace Bash for scripting?
« Reply #24 on: March 21, 2023, 08:23:33 am »
Interesting results.  You might also want to give tcc a try on your Mac-mini.

Tcc is an ANSI C compiler that is optimized for fast compilation and it can be used in the same style as bash, perl, and other interpreters by including the following at the top:

  #!/bin/tcc -run
  <your C program here...>

You don't need the intermediate step of generating an executable.

Wow, never heard of it. Live and learn. It's an interesting thing, however, what would a real use case be for it? Hmm...
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf