bash vs sh: parameter not set

whired123

Member
Joined
Nov 15, 2021
Messages
146
Reaction score
9
Credits
1,067
Code:
$ tree
├── bash
└── sh


$ cat bash
#!/bin/bash -u
echo $USER
echo $UID


$ cat sh
#!/bin/sh -u
echo $USER
echo $UID





$ ./bash
my-name
1000

$ ./sh
my-name
./sh: 3: UID: parameter not set

In summary

bash: echo $USER
Why does it work?

bash: echo $UID
Why does it work?

sh: echo $USER
Why does it work?

sh: echo $UID
Why doesn't it work?

Four questions, four answers (better five).
Ordered, clear and exhaustive answers.





sh: echo $UID
Why doesn't it work?
 


Perhaps consider bashisms:
Code:
$ cat bashfile
#!/bin/bash -u
echo $USER
echo $UID

$ cat shellfile
#!/bin/sh -u
echo $USER
echo $UID

$ checkbashisms shellfile
possible bashism in shellfile line 3 ($UID should be "$(id -ru)"):
echo $UID

$ checkbashisms bashfile
The checkbashisms executable is in the devscripts package.
 
Last edited:
A lot of shell variables are not set by default.
mmmhhh...

By doing a search, I understood that there are environment variables, and internal shell (e.g. bash) variables
Evidently UID is an internal variable.
 
Linux distros are pretty uniquely designed to allow others to set the variables, you have to define them in ~/.bashrc
Looking at ~/.bashrc I think I see where aliases and programmable features would be added.
I stick with Bash I've never tinkered with zsh or the like.

Code:
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi
 
no, I didn't really understand
The issue presented in post #1 appears to be about the difference between the behaviour of the shell invocations: /bin/bash and /bin/sh.

The differences in output where /bin/bash reads $UID, but /bin/sh doesn't read it, is the result of the more limited default capabilities of the historically earlier shell /bin/sh, than its more modern successor /bin/bash.

Here is a relevant quote from the bash man page:
If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.

Note that when the shell running on a system is /bin/bash, and the shell /bin/sh is invoked, one needs to check what executable /bin/sh is running or linked to. In current debian, /bin/sh is linked to the dash shell:
Code:
$ ls -al /usr/bin/sh
lrwxrwxrwx 1 root root 4 Feb  5 00:14 /usr/bin/sh -> dash

In other distros, it may be that /bin/bash is supplying the /bin/sh capability in which case the above quote would apply.

Looking at the dash man page one finds the following comment:
dash is the standard command interpreter for the system. The current version of dash is in the process of being changed to conform with the POSIX 1003.2 and 1003.2a specifications for the shell.
....
Only features designated by POSIX, plus a few Berkeley extensions, are being incorporated into this shell.

What is in common between /bin/bash's invocation of /bin/sh, and /bin/dash's invocation, is that they strive to conform to POSIX standards to a large degree. The full capabilities of the bash shell however, include a superset of functions which are not POSIX compliant.

The inference, in relation to the issue in post #1, is that /bin/bash has had the $UID variable set somewhere in the filesystem, but /bin/sh hasn't.
 
Last edited:
Moving this to Command Line, where bash and scripting inquiries are also covered.

Wizard
 
If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.

If bash is invoked with the name sh

Meaning what?
In other distros, it may be that /bin/bash is supplying the /bin/sh capability
Meaning what?
The inference, in relation to the issue in post #1, is that /bin/bash has had the $UID variable set somewhere in the filesystem, but /bin/sh hasn't.
$UID variable set somewhere in the filesystem
Meaning what?
 
If bash is invoked with the name sh

Meaning what?

Meaning what?

$UID variable set somewhere in the filesystem
Meaning what?
Bash being invoked with name sh simply means that when /bin/sh is called, such as within a script, it is the bash shell that executes it as if it were the more POSIX compliant shell known as sh, rather than as the full bash shell with all its capability including its bashisms.

If /bin/sh is a link to /bin/bash, which it is in some distros, it means that bash is supplying the sh capability and there is not a separate executable to execute sh.

In relation to environment variable's origins in the system, some environment variables are set by the shell, some are set in the filesystem, some are set by the system, within the executables.

Examples of environment variable set in the shell are those set as built-in to bash, such as:
Code:
$ echo $MAIL
/var/mail/ben
 
$ echo $HISTFILE
/home/ben/.bash_history

An examples of an environment variable set in the filesystem is the following:
Code:
$ grep PATH /etc/profile
  PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
  PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
export PATH

An examples of an environment variable set within an executable is UID.
UID is set by the system at login when the user is logged in and it is based on the user's account. There's no need for separate configuration of UID unlike other environment variables. It does not need to be explicitly defined in files like /etc/profile. It's automatically assigned by the system and available in all shells once a user logs in.

If one checks the source code of the login program from here: https://github.com/util-linux/util-linux/blob/master/login-utils/login.c, one can see that it depends on the header file: unistd.h, which installs at /usr/include/unistd.h if the libc6-dev package is installed. In that header file one finds:
Set the user ID of the calling process to UID
Thus, it appears that UID is built into the login executable from which it's assigned.
 
In relation to environment variable's origins in the system, some environment variables are set by the shell, some are set in the filesystem, some are set by the system, within the executables.
Set in the filesystem?
If anything, set by the system for the file system
An examples of an environment variable set in the filesystem is the following:
Code:
$ grep PATH /etc/profile
  PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
  PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
export PATH
Why is there a double declaration of PATH?
An examples of an environment variable set within an executable is UID.
Actually it is also available in the shell (outside the scripts)
If one checks the source code of the login program from here: https://github.com/util-linux/util-linux/blob/master/login-utils/login.c,
I don't see anything
 
Perhaps you "don't see anything" because you've misunderstood the sentence which needs to be read in its entirety to make the intended sense.

The comment you made in post #15 that UID is also available "in the shell (outside the scripts)" has no bearing on the observation being made in post #14 which was about where the environment variable was set in the system, not about its use. It's unclear to me as to why your comment was made except perhaps another misunderstanding of my text.

It's important to understand that post #14 was merely showing some examples of the origins of some environment variables and was not meant to be comprehensive on the issue in any way. Rather it was concerned to provide some understanding which could throw light on the matter you initially raised in post #1 as to the difference in shell behaviour in relation to environment variables.

My references in the posts I made were to manual pages and the source code which are where the canonical answers are to be found for your queries. There are other sources of an explanatory nature online which may be useful on the issue, but I found the explanations in the manual pages and source sufficient. You may not be satisfied with those answers or that approach. That's entirely your prerogative. I helped as I could so far as I understood the issue. I don't wish to be misunderstood. For different issues you can always start a new thread to give any new issue its due and I'm sure help will be forthcoming.
 
Last edited:
Trying things (setting variables, editing the ./bashrc) and then applying them is one way to learn how things work with Linux. If you don't like the results you get, you can always undo what you've modified.
 
Trying things (setting variables, editing the ./bashrc) and then applying them is one way to learn how things work with Linux. If you don't like the results you get, you can always undo what you've modified.
Does it need to be hidden though? Generally you hide those kinds of files to set them apart from the other files you manipulate...seems kinda weird at first glance but it makes sense.
 
Grazie per avermi costretto a usare Google Translate...

I file nascosti sono preceduti da un "." . I file nascosti esistono per distinguerli dai file non nascosti e non vengono visualizzati a meno che tu non ne faccia esplicita richiesta.

Dato che ovviamente non vuoi provare a interagire con me in una discussione, usa Google per cercare "hidden file" e impara a fare ricerche da solo.
 


Follow Linux.org

Members online


Top