Quantcast

umm BASH gurus, what does the typo $!/bin/bash do?

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

umm BASH gurus, what does the typo $!/bin/bash do?

David C. Rankin
Guys,

        This was bizarre. Doing a quick script, I accidentally did a $!/bin/bash
instead of #!/bin/bash. The script gave no output, but appeared to be
struggling much longer than it should (~1 sec) then would exit normally. No
error no nothing. Something worked though. I had set a trap to remove a temp
dir in it and provide output. When I ssh'ed into another box and came back,
evidently the EXIT signal was generated and the trap ran -- even though it the
script defined $! instead of #!.

        Can anybody tell me, or point me to any info, concerning just what $! did??

--
David C. Rankin, J.D.,P.E.
Rankin Law Firm, PLLC
510 Ochiltree Street
Nacogdoches, Texas 75961
Telephone: (936) 715-9333
Facsimile: (936) 715-9339
www.rankinlawfirm.com
--
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: umm BASH gurus, what does the typo $!/bin/bash do?

Joachim Schrod
David C. Rankin wrote:

> Guys,
>
> This was bizarre. Doing a quick script, I accidentally did a $!/bin/bash
> instead of #!/bin/bash. The script gave no output, but appeared to be
> struggling much longer than it should (~1 sec) then would exit normally. No
> error no nothing. Something worked though. I had set a trap to remove a temp
> dir in it and provide output. When I ssh'ed into another box and came back,
> evidently the EXIT signal was generated and the trap ran -- even though it the
> script defined $! instead of #!.
>
> Can anybody tell me, or point me to any info, concerning just what $! did??

Normally, I script that has $!/bin/bash in its first line, should
start an interactive bash and wait for further input. I.e., I don't
think it exited normally, you just got a same-looking prompt from a
subshell. When you then enter "exit" or type Ctrl-D the bash is
finished and the rest of this script will be executed.


Try it:
A basic example:

    puma:tmp $ cat try.sh
    $!/bin/bash

    echo hallo

Let's see which process we are in:

    puma:tmp $ ps -fp $$
    UID        PID  PPID  C STIME TTY          TIME CMD
    schrod    6080  6079  0 09:44 pts/8    00:00:00 bash

Well, our process id is 6080.
Execute the script and check which process we are in now:

    puma:tmp $ ./try.sh
    puma:tmp $ ps -fp $$
    UID        PID  PPID  C STIME TTY          TIME CMD
    schrod    6190  6189  0 09:46 pts/8    00:00:00 /bin/bash

As you'll see, a different process, with process id 6190. (The
parent process id 6189 is the try.sh-process that has 6080 as
parent.) No exit that sub-shell.

    puma:tmp $ exit
    hallo

Rest of the script (echo hallo) is executed, as you can see.


Are you sure that the trap run? The file was not there -- but was
it created in the first place? Your trap statement in the shell
script will never be reached and thus the trap should not be set up
at all.


Technical Background:

Concerning #! as the first 2 chars in a script: This is necessary
for the execution of this command with the system call exec() (or
one of its siblings, like execve()). Then it provides the "magic
number" for the loader to handle this "executable". I.e., it is
necessary when called from another program or with "exec" from
another shell script. It is not necessary when called interactively
from a bash session.

Thus, the first line was $!/bin/bash. $! expands to empty, so it's
just a line /bin/bash. That line causes bash to be executed. Since
there are no further arguments, an interactive shell is started.


HTH,
        Joachim

--
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Joachim Schrod Email: [hidden email]
Roedermark, Germany

--
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: umm BASH gurus, what does the typo $!/bin/bash do?

John Andersen-2
In reply to this post by David C. Rankin
David C. Rankin wrote:

> Guys,
>
> This was bizarre. Doing a quick script, I accidentally did a $!/bin/bash
> instead of #!/bin/bash. The script gave no output, but appeared to be
> struggling much longer than it should (~1 sec) then would exit normally. No
> error no nothing. Something worked though. I had set a trap to remove a temp
> dir in it and provide output. When I ssh'ed into another box and came back,
> evidently the EXIT signal was generated and the trap ran -- even though it the
> script defined $! instead of #!.
>
> Can anybody tell me, or point me to any info, concerning just what $! did??
>


Larry Wall 'splains it all...  http://tldp.org/LDP/abs/html/sha-bang.html (lower part)

You don't actually need the #! in a bash script if bash is your default shell.

So it was probably trying to figure out what $ meant.
Then it saw the !.

When you type a word preceeded by an "!", bash thinks you want to recall a previous command
or "event".  It happens in interactive shells, when the C-Shell-styled history expansion
(”!searchword”) is enabled. This is the default.


Then it probably recovered and just continued.
--
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: umm BASH gurus, what does the typo $!/bin/bash do?

Brian K. White
In reply to this post by David C. Rankin


David C. Rankin wrote:

> Guys,
>
> This was bizarre. Doing a quick script, I accidentally did a $!/bin/bash
> instead of #!/bin/bash. The script gave no output, but appeared to be
> struggling much longer than it should (~1 sec) then would exit normally. No
> error no nothing. Something worked though. I had set a trap to remove a temp
> dir in it and provide output. When I ssh'ed into another box and came back,
> evidently the EXIT signal was generated and the trap ran -- even though it the
> script defined $! instead of #!.
>
> Can anybody tell me, or point me to any info, concerning just what $! did?
>  

My guess is simply that $! expands to nothing, so effectively the line
is just "/bin/bash"
Since the first chars of the first line were not #! then there was
nothing special about the first line.
It was the same as if you had nothing on the first line and had just
/bin/bash on some lower line.
I leave it to you to contemplate what that would be like.
You'd get a prompt exactly like the one you were on before running the
script.
So, you'd think the script exited, but no you were still in the script,
still busy executing the first line, /bin/bash, until you typed exit or
hit ctrl-d, (/bin/bash finishes), at that point the rest of the script
would run.

--
bkw

--
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: umm BASH gurus, what does the typo $!/bin/bash do?

Joachim Schrod
In reply to this post by David C. Rankin
John Andersen wrote:

> David C. Rankin wrote:
>>
>> Can anybody tell me, or point me to any info, concerning just what $! did??
>
> So it was probably trying to figure out what $ meant.
> Then it saw the !.
>
> When you type a word preceeded by an "!", bash thinks you want to recall a previous command
> or "event".  It happens in interactive shells, when the C-Shell-styled history expansion
> (”!searchword”) is enabled. This is the default.

Ahem, no. $! is a standard bash variable. From the bash manual:


3.4.2 Special Parameters
------------------------

The shell treats several parameters specially.  These parameters
may only be referenced; assignment to them is not allowed.
[...]

`!'
     Expands to the process ID of the most recently executed
     background (asynchronous) command.

Since there has not been any background process in this subshell,
it expands to the empty string.

        Joachim

--
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Joachim Schrod Email: [hidden email]
Roedermark, Germany

--
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: umm BASH gurus, what does the typo $!/bin/bash do?

David C. Rankin
In reply to this post by Brian K. White
On Friday 02 October 2009 03:26:05 am Brian K. White wrote:
> So, you'd think the script exited, but no you were still in the script,
> still busy executing the first line, /bin/bash, until you typed exit or
> hit ctrl-d, (/bin/bash finishes), at that point the rest of the script
> would run.
>

        Yah, but you out to have seen all the output when I typed

strace ./scriptname

:p

--
David C. Rankin, J.D.,P.E.
Rankin Law Firm, PLLC
510 Ochiltree Street
Nacogdoches, Texas 75961
Telephone: (936) 715-9333
Facsimile: (936) 715-9339
www.rankinlawfirm.com
--
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: umm BASH gurus, what does the typo $!/bin/bash do?

Joachim Schrod
In reply to this post by Brian K. White
David C. Rankin wrote:

> On Friday 02 October 2009 03:26:05 am Brian K. White wrote:
>> So, you'd think the script exited, but no you were still in the script,
>> still busy executing the first line, /bin/bash, until you typed exit or
>> hit ctrl-d, (/bin/bash finishes), at that point the rest of the script
>> would run.
>>
>
> Yah, but you out to have seen all the output when I typed
>
> strace ./scriptname

Then the $!/bin/bash was not in the first line:

puma:tmp $ strace ./try.sh
execve("./try.sh", ["./try.sh"], [/* 145 vars */]) = -1 ENOEXEC
(Exec format error)
dup(2)                                  = 3
fcntl64(3, F_GETFL)                     = 0x8002 (flags
O_RDWR|O_LARGEFILE)
fstat64(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 8), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0) = 0xb7f6d000
_llseek(3, 0, 0xbff8b20c, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
write(3, "strace: exec: Exec format error\n", 32strace: exec: Exec
format error) = 32
close(3)                                = 0
munmap(0xb7f6d000, 4096)                = 0
exit_group(1)                           = ?

As I wrote, such a file only works when called by bash directly,
not via exec(), which is used by strace.

        Joachim

--
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Joachim Schrod Email: [hidden email]
Roedermark, Germany

--
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: umm BASH gurus, what does the typo $!/bin/bash do?

David Haller-4
Hello,

On Fri, 02 Oct 2009, Joachim Schrod wrote:
>Then the $!/bin/bash was not in the first line:
>
>puma:tmp $ strace ./try.sh
>execve("./try.sh", ["./try.sh"], [/* 145 vars */]) = -1 ENOEXEC
>(Exec format error)
[..]
>As I wrote, such a file only works when called by bash directly,
>not via exec(), which is used by strace.

But without strace, the kernel feeds the file to the user's shell.

$ cat t.sh
$!/bin/bash
echo Hello

$ strace bash -c './t.sh' ## shortened output, my comments after '###'
### start the 'bash -c' process
execve("/bin/bash", ["bash", "-c", "./t.sh"], [/* 103 vars */]) = 0
[..]
### try exec t.sh
execve("./t.sh", ["./t.sh"], [/* 100 vars */]) = -1 ENOEXEC (Exec format error)
### as commented
open("./t.sh", O_RDONLY|O_LARGEFILE)    = 3
read(3, "$!/bin/bash\necho Hello\n", 80) = 23
close(3)
[..]
open("./t.sh", O_RDONLY|O_LARGEFILE)    = 3
[..]
read(3, "$!/bin/bash\necho Hello\n", 23) = 23
### now the script is fed to the user's default-shell and the first
### line is executed (i.e. start the /bin/bash after the $!):
fork()                                  = 7811
### within the 'wait' the interactive /bin/bash started from script
### is running, I exit by pressing Ctrl-d:
wait4(-1, dh@slarty[11]: (0)$ exit
WIFEXITED(s) && WEXITSTATUS(s) == 0], 0, NULL) = 7811
[..]
--- SIGCHLD (Child exited) ---
wait4(-1, 0xbfffe348, WNOHANG, NULL)    = -1 ECHILD (No child processes)
### we're back to the t.sh script
[..]
read(3, "echo Hello\n", 23)             = 11
write(1, "Hello\n", 6Hello
)
read(3, "", 23)                         = 0
munmap(0x40014000, 4096)                = 0
_exit(0)                                = ?

Using the extra bash -c simulates the behaviour you'd get without
strace.

Any questions? ;)

-dnh

--
If you think, you're wrong, you might be right!
--
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: umm BASH gurus, what does the typo $!/bin/bash do?

Joachim Schrod
In reply to this post by Joachim Schrod
David Haller wrote:
>
> $ strace bash -c './t.sh' ## shortened output, my comments after '###'
> [..]
>
> Using the extra bash -c simulates the behaviour you'd get without
> strace.
>
> Any questions? ;)

Yes -- why would one use strace to analyze that problem in the
first place?

A simple "bash -x", or at the max "bash -vx", would be better,
wouldn't it?

        Joachim

--
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Joachim Schrod Email: [hidden email]
Roedermark, Germany

--
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Re: umm BASH gurus, what does the typo $!/bin/bash do?

David Haller-4
Hello,

On Sat, 03 Oct 2009, Joachim Schrod wrote:

>David Haller wrote:
>>
>> $ strace bash -c './t.sh' ## shortened output, my comments after '###'
>> [..]
>>
>> Using the extra bash -c simulates the behaviour you'd get without
>> strace.
>>
>> Any questions? ;)
>
>Yes -- why would one use strace to analyze that problem in the
>first place?

Why not? Routine?

>A simple "bash -x", or at the max "bash -vx", would be better,
>wouldn't it?

Better? Nah. Sufficient? Maybe. With strace, you get to see what
really gets done. Just to see what gets executed, esp. if your shell
is not /bin/bash.

Start e.g. a ksh and do a ./t.sh (or whatever) there, with -x and with

strace -o t.strace -f -eprocess,open,read,write /bin/ksh -c './t.sh'

(which emulates typing just './t.sh' running under strace)

I'm too tired right know to check more details, but I think you'll
find something interesting in the t.strace ;)

E.g. that 't.sh' is actually executed by '/bin/sh'!

3190  execve("./t.sh", ["./t.sh"], [/* 103 vars */]) = -1 ENOEXEC (Exec format error)
3190  execve("/bin/sh", ["/bin/sh", "./t.sh"], [/* 103 vars */]) = 0

The kernel finds no valid executable, no valid #! line, and thus tries
feeding it to /bin/sh ...

You won't detect that difference with '-x' or '-vx'.

Satisfied?

(I'm too tired for more now, ask again, and I'll try ;)

-dnh, considering strace and ltrace the swiss-knives of the
    first(-and-a-half)-step of debugging (i.e. before using gdb,
    reading source etc. ;)

--
> (void *)'\0'
Didn't you see the sign?  It said
   VOID WHERE PROHIBITED
Don't tell me you can't C.         -- the Internet Oracle [#1307-01]
--
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Loading...