What shell would you use for (shell) scripting in Linux servers in 2022?

My shop was a HP UX/AIX shop. For applications which my team work on, I have several shell scripts and all are written in ksh.
Now, all of my applications got migrated to Red Hat Linux 7.9 servers.

I have been asked to create a shell script for a relatively complex feature. Since I am not an expert in shell scripting, I think it will take at least 3 weeks for me to develop it.

Question 1. In a modern Linux environment, should I write the shell scripts in bash (Bourne Again Shell) or stick to korn shell ? Or, is there some other shell which I should consider ?

Question 2. In the legacy shell scripts which run on korn shell, I have noticed that there is no shebang like #!/bin/ksh (written at the beginning of the script). In the old HP-UX/AIX servers, the default shell was korn shell, so I guess the scripts just ran on korn shell.

But, isn't it a bad practice not to use shebang ?
I mean, if I decide to use bash scripting language for my shell scripts, isn't it better to use #!/bin/bash at the top of script as the shebang ?
Or is the shebang deliberately skipped to avoid some portability issues?

Welcome to the forum !
We hope you find this to be a friendly and helpful place...

I will give my thoughts to Q2 to start with as I started (except Linux pre v1 at home and SunOS at university) to work and learn unix on HP-UX 8...

  • on HP-UX and the AIX I had to administer the default shell was (/usr)/bin/ksh, so you could ignore the shebang first line, only if for some reason you were to call your scripts by cron, depending how you coded issues arise...
    and the default shell /usr/bin/ksh was for all users except root, for a very good reason, sh is statically linked...
    The shebang line calls the named shell whatever shell you are using, and so it is there for portability.

If you must write your scripts in a shell, personally I would write the core code using statements that would work in any 'sh' style shell, sh, ksh, bash or pdksh.

You can add the

#!/bin/bash or whatever you use, and if you want to change the shell there will be minimal logic changes.

Back in the nineties I was working on UNIX servers at work and a Linux desktop at home. I made a few relatively minor changes to my scripts.

For instance, I had a .kshrc script and wanted a very similar .bashrc script. For that matter I wanted to be able to use similar scripts in the Bourne Shell, (sh) and also the Z shell, zsh.

All of them are similar but not identical but it is possible when writing scripts to use constructs common to all of them; then changing the script or even dropping the shebang and using a script for any sh style shell is possible.

Maybe that's not optimal for all coding but it sure makes portable scripting easier!

I don't know current status HP/UX, but it has been Posix shell in HP/UX (/usr/bin/sh), which is very similar to the Korn shell (ksh93). I think that HP/UX ksh is ksh88. ksh88 is subset of ksh93.

So if you have lot of script using sh or ksh88, then those script will work fine in Linux distros, if you install ksh.
It is ksh93.

If you have
#!/usr/bin/ksh in your script and install ksh to the Linux, then you don't need change anything = default. Applies to builtin commands.
The most of GNU commands include X/Open (HP/UX use X/Open standards or has used) standards options and arguments. GNU has added options and arguments to many commands. So most of external commands which you have used in HP/UX, works fine also in Linux distros.

I'll say that change scripting language to the bash (which is also almost posix sh compatible as ksh), you not get so much new builtin properties that you need to change scripting shell. If you change shell, there are some builtin properties in ksh/posix-sh which not work in bash. Ex. typeset you have maybe used.

That was my opinion. I have walked same path and still I use ksh93 in my all scripts. Lazy? Maybe. You can use bash in your command line and scripts are still ksh. No problem.

To emulate ksh, you can put the following on top:

#!/bin/zsh
emulate ksh

Using zsh and emulate ksh is quite good, certainly better than

#!/bin/bash
shopt -s lastpipe

Even the latter should "eat" most of your scripts with no shebang or #!/bin/sh

Pitfalls with bash:

a number with a leading 0 is interpreted as octal. (This feature gives more headaches than benefits; a "misfeature"). The fix is to prefix it with 10#.

No floating point. ksh88 cannot do fp arithmetic, but it automatically converts a fp number to an integer.
Where bash bails out. A fix is ${num%.*}

Both fixes combined: 10#0${num%.*}

A last word on "no shebang": this uses the kernel default, and it should be /bin/sh.
In HP-UX and AIX /bin/sh should be a link to ksh. Test it with
ls -li /bin/sh /bin/ksh
Likewise, in many Linux distros /bin/sh is a link to bash.

Hello,

Welcome to the forum ! As others have said here, there are certainly ways of continuing to run your Korn shell scripts on RHEL. The easiest way, I would say, is just to install ksh and go with that. And yes, I would definitely include a shebang line in any and all scripts that you write, just as a matter of good practice. That removes any chance of ambiguity - and in the case that you are using any Korn-specific syntax or features, would be a necessity, since by default Linux would run your scripts via Bash, and then you would encounter an error or unexpected behaviour.

The Korn shell has been part of RHEL for some time now, and is still present in RHEL 7 and RHEL 8. And looking at the beta of RHEL 9, it seems to still be included in there too. So from a future-proofing point of view, you have nothing to worry about if you write and deploy Korn shell scripts on RHEL.

One word of advice however: I wouldn't go changing the default shell of root or any other system-critical users from Bash to Korn (or anything else, for that matter). The system is written to expect Bash behaviour in its startup scripts, and it's seldom a good idea to change the default shell for root or other system service accounts. Leave that as-is, and just set your Korn shebang line, and you should be fine.

Hope this helps !

Thank You guys.

Going back to question1. So, in a modern Linux environment like RHEL 7.9, choosing bash as the scripting language should be fine. Right ?

Question3.
masinick said
If you must write your scripts in a shell, personally I would write the core code using statements that would work in any 'sh' style shell, sh, ksh, bash or pdksh

In the shell script which I need to develop, I need menus like the one shown in the below example.
Bash has the SELECT builtin like below. After removing the bash shebang, I ran the below script from korn shell and it worked fine.
So, is it safe to assume that these shell builtins are pretty much interoperable ?

#!/bin/bash
PS3='Choose your preferred currency: '

echo "============="
echo "Script Menu"
echo "============="
currencies=("Euro" "Yen" "Ruble" "Quit")
select fav in "${currencies[@]}"; do
    case $fav in
        "Euro")
            echo "Europeans use $fav everyday!"
	    # optionally call a function or run some code here
            ;;
        "Yen")
            echo "Chinese use $fav everyday."
	    # optionally call a function or run some code here
            ;;
        "Ruble")
            echo "Russians use $fav everyday"
	    # optionally call a function or run some code here
	    break
            ;;
	"Quit")
	    echo "User requested exit"
	    exit
	    ;;
        *) echo "invalid option $REPLY";;
    esac
done

Bash.

Yes, use bash; it's standard and will definitely work on scripts similar to the one you shared.

Other shells are available but why bother when bash is included?

Yes, it is a poor coding practice to write any script without the shebang.

Why?

The most obvious reason is that when anyone looks at a file, that person can easily see the scripting language without trying to analyze the code.

Of course, "big ego" experts will say "it is obvious" what language the code it written in (which is another problem we see, especially in academic-like situations and forums).

However, in most real world situations, people who write scripts change jobs, move on, pass away, etc and more-often-than-not someone who is NOT an expert will have to modify or maintain the script. So, putting a shebang at the top if the script is a very professional thing to do, always, regardless of the benefits of specifying the interpreter.

I recently completely a huge project where an entire accounting system was written decades ago and the coder died; leaving the company in a panic. For two years (while the original software developer was terminally ill), they could not find anyone to make changes they required based on changes to their business.

The original program was written in AWK "decades" ago; and it was completely undocumented. Working with the ops manager from that organization, I rewrote the entire application in Ruby on Rails and it has been in production for almost a year now.

The organization is extremely happy now to not have an AWK-based system, with data stored in odd "flat files", nearly impossible to query, running their entire accounting practice . Today, they are very happy to have a modern, web-based Ruby on Rails, database-driven application which is easy to query, modify and build new features.

No to mention, everyone loves the web-based UI :slight_smile: No one at that company liked trying to do their daily business on an ASCII terminal based UI, of course; and now they have a responsive web app they can use on desktop or mobile, from anywhere on the planet, if they choose.

Using a shebang is the LEAST thing a professional can do to document their code!!

Even posting code on this site, a shebang is always a good thing, even for code fragments, as in this code posted above:

Screen Shot 2022-05-24 at 9.15.48 AM

If you like that script works for every process like any command = execute privilege has set, then
scripts have to include shebang = #!interpreter_path in 1st line (sh, ksh, zsh, dash, perl, awk, ...)
even it's only one line.

Since about 1990 I have used "own shell" => shebang. On that time our sw were used so many diffrent *nix distros.

/bin/sh was usually Bourne shell, but not always = we got big problems. Just like Linux distros /usr/sh is some almost Bourne shell or posix-sh compatible (ksh, dash, ash, bash, zsh, ...).
And previous Pro's have said - don't overwrite it using your shell - system scripts use it and maybe not work after your "sh update".
Result could be "no boot today" after reboot. I have tested it - it was long night ...

When I 1st time saw that sh is some, but maybe not what I need in my scripts, I have installed always on destination system my shell for my scripts. Of course I have not own shell, but I know that my scripts need ksh93 compatible shell.
=> I copy ksh93 compatible shell to the /usr/local/bin/myksh
=> My shell shebang is always my own in every environment.
=> after that solution I have never been problem to run our scripts in every different *nix systems.

Some negative:

  • if system update in this case ksh93 shell, I need manually copy new version to overwrite copy of myksh
#!/usr/local/bin/myksh

I'm not saying what is correct shell for scripting, but whatever you use, I can recommend "myshell" method.

This is not a true statement. Please be careful with your words, @kshji

What you should have said was:

Every script should include shebang = #!interpreter_path in 1st line (sh, ksh, zsh, dash, perl, awk, ...)

If what you said was true, then most scripts would not even run :slight_smile:

In other words, the SHOULD have a shebang, but if the do not have a shebang, scripts often will run, based on how everything is configured.

@kshji , just in case you are not convinced, check out this very simple example:

macos$ cat hello
echo "HELLO WORLD"
macos$ ./hello
HELLO WORLD
macos$ 

Obviously, your statement "Every scripts have to include shebang ..." is not accurate because in the very trivial example, there is no shebang, and the script runs as it should :slight_smile:

(Sorry for correcting you and providing such a trivial example).

Of course, anybody running your script can simply over-ride the shebang, thereby possibly invalidating the syntax. If you specify a shell before the script name, that shell treats the shebang as a comment. The shebang is only effective if the kernel itself is treating the script as an executable.

$ cat zoo
#! /bin/bash
pstree -p $PPID

$ ./zoo
bash(4151)───zoo(9912)───pstree(9913)
$ sh zoo
bash(4151)───sh(9915)───pstree(9916)
$ ksh zoo
bash(4151)───ksh(9919)───pstree(9920)
$ bash zoo
bash(4151)───bash(9928)───pstree(9929)
$