set, export, env & subshell (was: export) 

Newsgroups: comp.unix.shell
> > > What exactly does export mean? I mean, does it like kind of declaration
> > > or something?
> > >
> > > What the impact would it be if the order of setting and exporting
> > > is different.
> > >
> > > Let me explain with examples:
> > >
> > > # case 1
> > > export PS1
> > > PS1='$ '
> > >
> > > # case 2
> > > PS1='$ '
> > > export PS1
> > >
> > > # case 3
> > > PS1='$ '
> > > export PS1
> > > PS1='# '
> > >
> > > what is the system status for above 3 cases. Thanks
> >
> > They all end up being the same in the end.  An export means to make
> > the variable available to all child processes.  Without the export,
> > the child process won't inherit the parents nonexported variables.
> > Since you are all in the one process setting the PS1 and exporting
> > it, all 3 will export the variable to the children.  The export also
> > only needs to be executed once, just like typeset -x.  So for your
> > third example, where you change the value of PS1 after the export,
> > the variable is STILL exported so the new value will be used by the
> > children called after that point.
>
> So I thought. I never thought something else until I used bash2.03
> in linux debian.
>
> bash-2.03$ set | grep PS1
> PS1='\s-\v\$ '
> bash-2.03$ env | grep PS1
> bash-2.03$ export PS1
> bash-2.03$ env | grep PS1
> PS1=\s-\v\$

Whay are you using 'env' with bash? env is a csh-ism (actaully usually a separate command, e.g. /usr/bin/env). Use export.

> so far so good...
>
> bash-2.03$ sh -c 'echo $PS1'
>
> bash-2.03$
>
> and, now, why the sub-process 'sh' didn't get the variable? Does it
> mean bash for debian is different? I tested on Solaris and it worked
> as I expected (PS1 get printed).

I tested it on RH5.2 running bash-1.14.7 (eeek!) and got the same result as above. I then tried the following on a SunOS 5.7 and got this:

bash$ ls -l $(cat /etc/shells) $(command -v ksh) $(command -v bash)
-r-xr-xr-x   1 bin      bin       151976 Oct  6  1998 /bin/csh*
-r-xr-xr-x   3 bin      root       91668 Oct  6  1998 /bin/sh*
-r-xr-xr-x   2 bin      root      257444 Sep  1  1998 /sbin/sh*
-r-xr-xr-x   1 bin      bin       151976 Oct  6  1998 /usr/bin/csh*
-r-xr-xr-x   2 bin      bin       192764 Oct  6  1998 /usr/bin/ksh*
-r-xr-xr-x   3 bin      root       91668 Oct  6  1998 /usr/bin/sh*
-rwxr-xr-x   1 gnu      gnu       606724 Dec 18  1996 /usr/local/bin/bash*

Note that sh _doesn't appear_ to be ksh (diff reportes them as being different too: well it would really, since it comapares file size first). I *think* that sh is an original version of Bourne.

[me@machine me]$ sh -c 'echo $PS1'
[me@machine me]$ ksh -c 'echo $PS1'
[me@machine me]$ bash -c 'echo $PS1'
[\u@\h \W]$

Moral of the story? You should *never* rely on PS1 being set in a non-interactive shell session. If you did the following, however, then it would work:

[me@machine me]$ ksh -c 'PS1="hello >" ; echo $PS1'
hello >
[me@machine me]$ sh -c 'PS1="hello >" ; echo $PS1'
hello >
[me@machine me]$ bash -c 'PS1="hello >" ; echo $PS1'
hello >

The PS1 variable is a special case though, as it is automatically exported by the shell, e.g. the above is equivalent to:

sh -c 'export PS1="hello >" ; echo $PS1'

For a child shell to inherit it's parent's variables, that variable must be exported, e.g.

[me@machine me]$ PSTEST="hello >"
[me@machine me]$ bash -c 'echo $PSTEST'
[me@machine me]$ export PSTEST="hello >"
[me@machine me]$ bash -c 'echo $PSTEST'
hello >

so the above becomes:

[me@machine me]$ export PS1="$(echo $PS1)"
[me@machine me]$ksh -c 'echo $PS1'
[\u@\h \W]$
[me@machine me]$sh -c 'echo $PS1'
[\u@\h \W]$
[me@machine me]$bash -c 'echo $PS1'
[\u@\h \W]$

So, PS1 is only exported automatically to other _bash_ shells, not to ksh, or sh. Since bash aims to emulate sh as closely as possible when it is run as sh, that's why you don't see your new prompt.

I hope this clears it up for you. :-)

Cheers,

Dave.

set, export, env & subshell (was: export) 

|>>> What exactly does export mean? I mean, does it like kind of declaration
|>>> or something?
|>>>
|>>> What the impact would it be if the order of setting and exporting
|>>> is different.

In recent shell implementations, no difference. In very old Bourne shell implementations, "export" copies, so subsequent modifications to the variable don't go into the environment.

|> bash-2.03$ set | grep PS1
|> PS1='\s-\v\$ '
|> bash-2.03$ env | grep PS1
|> bash-2.03$ export PS1
|> bash-2.03$ env | grep PS1
|> PS1=\s-\v\$
|
| Whay are you using 'env' with bash? env is a csh-ism (actaully usually a
| separate command, e.g. /usr/bin/env). Use export.

He's using "set" to display local variables, and "env" to display environment variables. I'd use "printenv PS1", but there's nothing wrong with the way he's doing it. "export" wouldn't be useful.

| Note that sh _doesn't appear_ to be ksh (diff reportes them as being
| different too: well it would really, since it comapares file size
| first). I *think* that sh is an original version of Bourne.

Diff, ls etc. are not always good ways to identify shell implementation. When they're not identical files, the next step is "strings".

| ... The PS1 variable is a special case though, as it is automatically
| exported by the shell, ...

PS1 is not automatically exported, from bash or ksh.

$ unset PS1
$ PS1='CMD> '
CMD> printenv PS1
CMD>

Donn Cave

set, export, env & subshell (was: export) 

>and, now, why the sub-process 'sh' didn't get the variable? Does it
>mean bash for debian is different?

It means that sh is resetting PS1 on start-up. Try testing with a variable which has no special meaning to the shell.

Ken Pizzini

documented on: 2000.06.06 Tue 10:56:58