Differences Between Shell And Exec
Shell
SHELL invokes
/bin/sh
(or the shell defined by the
System.Shell property), and passes it a single command line.
/bin/sh
parses this command line exactly the same way it does in a normal shell. So,
SHELL "ls -l *.o >/tmp/list"
will do exactly the same as if you typed
ls -l *.o >/tmp/list
in a
terminal emulator under a shell. This is a lot of things, because the
shell has tremendous power. This command:
-
Splits the command line into several parts: executable to run, parameters to pass it, other constructs...
-
Searches for an executable named
ls
in the PATH
environment.
-
Substitutes
*.o
with all the .o
files in the current directory.
-
Prepares a redirection (the normal output of
/bin/ls
is redirected to /tmp/list
).
To summarize, the shell can do a lot of things, and the Gambas shell
command brings that power to you.
After
/bin/sh
is done with all this parsing/computing work, it invokes
an
exec()
system call, which loads and executes an executable, passing
it a number of parameters.
A program that is executed with the shell procedure will NOT be terminated when the Gambas program is terminated. You must either KILL the process or allow it to run until its normal termination.
Exec
The Gambas
EXEC instruction calls the
exec()
system call, bypassing the
shell. This is faster and less memory hungry, because you
invoke an external command without invoking
/bin/sh
, but you lose all
the power the shell has.
In fact, if you want to list all the
.o
files
in the current directory and put the result into
/tmp/list
without using
the powerful shell, you have to:
-
Search by yourself for the files.
-
Create an array of the names of those files.
-
Invoke
/bin/ls
and pass it an array which contains the -l
and all the filenames you found.
-
Redirect its standard output to a file, or use the FOR syntax to get the output directly into a Gambas event handler.
To conclude. If you run an EXEC in gambas, you must simply supply the
program name to execute and all its parameters. If you issue:
EXEC ["/bin/ls", "-l", "*.o", ">/tmp/list"]
you will invoke
/bin/ls
passing it the above parameters.
/bin/ls
will
(correctly) recognize the
-l
as a switch; but
*.o
and
>/tmp/list
will be recognized as files to look for, and no files named
*.o
will
exist. The
>/tmp/list
is a shell syntax, not a
/bin/ls
one, and
/bin/ls
will look again to for file named
>/tmp/list
.
A program that is executed with the EXEC procedure will be terminated when the Gambas program is terminated.
You can type
man sh
at the shell prompt; all of what you will read
there are shell capabilities, and none of them are available in EXEC.
The three most important things which are available in the shell, and
not available in EXEC are:
-
Pattern substitution.
.o
and the like are shell constructs.
-
Redirections and pipes.
>/foo/bar
, </foo/bar
, 2>&1 | command
and so on.
-
Variables like
$HOME
, $PATH
and so on.
But EXEC has a good advantage over
SHELL. If you have to invoke an
external command which has (or can have) unusual characters in the
command line, like
firefox http://someserver.com/doit.cgi?name=foo&reply=bar
SHELL (or, better,
/bin/sh
) will interpret characters like
?
and
&
, while EXEC will not.
So, if you need some shell capability, use
SHELL; otherwise use EXEC. Using SHELL saves typing, on the other hand,
but ONLY if you are sure that no strange characters (
?
,
&
,
$
, spaces, and
others) will appear in the command you are constructing.
In that last case, Gambas has a
Shell$ function
that quotes these "strange" characters for the SHELL instruction, so that you are sure
that any file name can be used with it.
See also