|
Softpanorama |
||||||
| Contents | Bulletin | Scripting in shell and Perl | Network troubleshooting | History | Humor | |
| News | Books | Unix Utilities | Recommended Links | Pipes | Shells | |
| Unix Find Tutorial/Using -exec option with find | Unix Xargs | tee | Unix script command | Admin Horror Stories | Humor | Etc |
The exec command replaces the current shell process with the specified command. Normally, when you run a command a new process is spawned (forked). The exec command does not spawn a new process. Instead, the current process is overlaid with the new command. In other words the exec command is executed in place of the current shell without creating a new process. The command implements Unix exec system call. It is a part of process control API, the group that also includes fork system call. See Fork and Exec Unix Model (PowerPoint).
Note: this is completely different command then Find command option -exec which permits execution of commands using found file as argument. Xargs is another command that provides means to build and execute command lines from standard input.
In no command arguments are given this command can modify file descriptors. In other words the exec command can also be used in shell scripts dynamically open, close, and copy file descriptors. That permits performing redirection of STDIN, STDERR, STDOUT and other file descriptors to various files inside the shell script, instead of command invocation string.
In other words in shell the exec command can serve as a substitute to OPEN and CLOSE commands that are common in regular scripting languages, like Perl and Python. Usage of those facilities makes shell script more user friendly.
The name of the command is identical to the name of a Unix system call which provides semantic of this command.
Syntax:
exec [ command ] [ arg ... ] exec fd<file exec fd>file
Arguments
There are two most common uses of exec command
exec bash
If you specify a command, the shell replaces itself in memory with the new command you specified. For example,
exec vi myfile
replaces the shell with the vi program text and places you in vi,
editing myfile. When you exit vi you exit the system because vi
has become your login interface to the operating system.
LOG=/var/opt/myscript/myscript.log exec 1>>$LOG exec 2>&1This is essentially equivalent to running the script as
./myscript &>> /var/opt/myscript/myscript.log # bash 4
./myscript >> /var/opt/myscript/myscript.log 2>&1 # earlier versions of bash and ksh 4
See Advanced Bash-Scripting
Guide/I-O Redirection for a good explanations of redirection in Unix shell
exec 3< inputfile # Opens inputfile with file descriptor 3 for reading. exec 4> outputfile # Opens outputfile with file descriptor 4 for writing. exec 5<&0 # Makes fd 5 a copy of fd 0 (standard input). exec 6>&p # Attach fd 6 to co-process.
You can also use the exec command to create a set of shell scripts that execute one another sequentially like stages of the process. Instead of spawning new processes each time you need to transfer the control to the next script you execute the exec command . For example:
while true
do
echo "Go to Mail, Editor, or eXit:"
read ANSWER
case "$ANSWER" in
[mM]) exec MAILX ;;
[eE]) exec ${EDITOR:=vi} ;;
[xX]) exec exit ;;
esac
done
Here the initial script is used to provide a menu and after selection was made serves no useful purpose. So it can be replaced by selected utility via exec call.
|
|
||||
| Bulletin | Latest | Past week | Past month |
|
Mar 07, 2009 | Adam Palmer
We have three relevant streams when dealing with passing data around on the command line. STDIN (0), STDOUT (1) and STDERR (2)
echo “hello” will return “hello” to STDOUT
echo “hello” | sed s/llo/y/g
Returns: ‘hey’echo “hello” will print “hello” to STDOUT which we pipe to sed’s STDIN. The shell will fork both processes, echo and sed, and create a pipe between one’s STDOUT to the other’s STDIN. A ‘broken pipe’ will occur when one terminates unexpectedly.
strace echo “hello” will print the system calls that the command makes. Lets say I just want to print out open() calls.
strace echo “hello” | grep open does not work. It seems that the grep is ignored.
This is because strace sends it’s output to STDERR and not STDOUT. In this case we must redirect STDERR to STDOUT so grep can pick it up on it’s STDIN.
strace echo “hello” 2>&1 | grep open will work successfully.
What if we want to redirect STDOUT and STDERR to a file? We simply redirect STDOUT to a file and then redirect STDERR to STDOUT.
strace echo “hello” >/tmp/strace.output 2>&1
A nonstandard method of achieving the same by redirecting everything in one go is strace echo “hello” &>/tmp/strace.output however this is not guaranteed to work across all implementations.
The exec command is used for redirection of file descriptors 0:9. Example:
> ksh $ exec 1>std.out $ dir ~/test $ .... $ exitIn the above example, all output directed to stdout from the command exec to the command exit is written on file std.out. To use file descriptor 5:> cat kexec # open file x.x by descriptor 5 with exec 5>x.x exec 5>x.x print -u5 "1. redirect print output to fd 5 opened by exec" print -u5 "2. prinf on fd 5" print -u5 "3. print on fd 5 again" exec 5<&- # close file x.x with exec 5<&- echo "\n verify x.x by cat\n"The kexec script listed above creates file x.x containing the script lines 1.-2.-3..
If the file descriptor is closed, any attempt to access closed file produces the following error message:> kexec kexec[13]: print: bad file unit numberexec may be used to execute a script but user is logged out exec is invoked when in parent shell.The read command reads input from the terminal as single variables, piped names or file redirected with exec as summarized in the following example.
> cat kread #!/bin/ksh #-----------kread: read data with Korn shell--------------------- # echo Proc $0: read command in Korn shell echo print "type a name> \c" # read var at promp read name print "typed name is: " $name print "\npiped read example:" print "apr may jun" | read a b c # pipe args print arg1 from pipe is $a print arg2 from pipe is $b print arg3 from pipe is $c print "\nread/write lines with exec redirection\n" exec 0<$1 # redirect i/o while read LINE do print $LINE done # #----------end script------------------ > kread Proc kread: read command in Korn shell type a name> any typed name is: any piped read example: arg1 from pipe is apr arg2 from pipe is may arg3 from pipe is jun read/write lines with exec redirection line 1 line 1 <ctrl>C >
Korn Shell Read Options -p read line form co-process -r do not treat \as continuation-s save input in history file -un read from file descriptor n The prompt can be specified in the read statement:
$ read var?promptIf var is not defined, input is assigned to variable REPLY. Field separator can be assigned with the IFS (Internal Field Separator) variable.
Example:> cat kpwd #!/bin/ksh #-----------kpwd: read example in Korn shell echo Proc $0: type pwd info with Korn shell echo read ok?"Type pwd info? (y/n)" #read with prompt [[ $ok = @([Nn])* ]] && exit 1 #test read variable echo pwd data are: echo "" IFS=: #set IFS to : exec 0</etc/passwd #redirect stdin to /etc/passwd # list users # while read -r NAME PAS UID GID COM HOME SHELL do print "acct= $NAME - home= $HOME - shell= $SHELL:" done #----------end script------------------ > kpwd Type pwd info? (y/n)y pwd data are: acct= john - home= /home/john - shell= /bin/tcsh: acct= mary - home= /home/mary - shell= /bin/tcsh: acct= tester - home= /d4/check - shell= /bin/sh: >
An exec <filename command redirects stdin to a file. From that point on, all stdin comes from that file, rather than its normal source (usually keyboard input). This provides a method of reading a file line by line and possibly parsing each line of input using sed and/or awk.
Example 16-1. Redirecting stdin using exec
1 #!/bin/bash 2 # Redirecting stdin using 'exec'. 3 4 5 exec 6<&0 # Link file descriptor #6 with stdin. 6 # Saves stdin. 7 8 exec < data-file # stdin replaced by file "data-file" 9 10 read a1 # Reads first line of file "data-file". 11 read a2 # Reads second line of file "data-file." 12 13 echo 14 echo "Following lines read from file." 15 echo "-------------------------------" 16 echo $a1 17 echo $a2 18 19 echo; echo; echo 20 21 exec 0<&6 6<&- 22 # Now restore stdin from fd #6, where it had been saved, 23 #+ and close fd #6 ( 6<&- ) to free it for other processes to use. 24 # 25 # <&6 6<&- also works. 26 27 echo -n "Enter data " 28 read b1 # Now "read" functions as expected, reading from normal stdin. 29 echo "Input read from stdin." 30 echo "----------------------" 31 echo "b1 = $b1" 32 33 echo 34 35 exit 0
Similarly, an exec >filename command redirects stdout to a designated file. This sends all command output that would normally go to stdout to that file.
Example 16-2. Redirecting stdout using exec
1 #!/bin/bash 2 # reassign-stdout.sh 3 4 LOGFILE=logfile.txt 5 6 exec 6>&1 # Link file descriptor #6 with stdout. 7 # Saves stdout. 8 9 exec > $LOGFILE # stdout replaced with file "logfile.txt". 10 11 # ----------------------------------------------------------- # 12 # All output from commands in this block sent to file $LOGFILE. 13 14 echo -n "Logfile: " 15 date 16 echo "-------------------------------------" 17 echo 18 19 echo "Output of \"ls -al\" command" 20 echo 21 ls -al 22 echo; echo 23 echo "Output of \"df\" command" 24 echo 25 df 26 27 # ----------------------------------------------------------- # 28 29 exec 1>&6 6>&- # Restore stdout and close file descriptor #6. 30 31 echo 32 echo "== stdout now restored to default == " 33 echo 34 ls -al 35 echo 36 37 exit 0
Example 16-3. Redirecting both stdin and stdout in the same script with exec
1 #!/bin/bash 2 # upperconv.sh 3 # Converts a specified input file to uppercase. 4 5 E_FILE_ACCESS=70 6 E_WRONG_ARGS=71 7 8 if [ ! -r "$1" ] # Is specified input file readable? 9 then 10 echo "Can't read from input file!" 11 echo "Usage: $0 input-file output-file" 12 exit $E_FILE_ACCESS 13 fi # Will exit with same error 14 #+ even if input file ($1) not specified. 15 16 if [ -z "$2" ] 17 then 18 echo "Need to specify output file." 19 echo "Usage: $0 input-file output-file" 20 exit $E_WRONG_ARGS 21 fi 22 23 24 exec 4<&0 25 exec < $1 # Will read from input file. 26 27 exec 7>&1 28 exec > $2 # Will write to output file. 29 # Assumes output file writable (add check?). 30 31 # ----------------------------------------------- 32 cat - | tr a-z A-Z # Uppercase conversion. 33 # ^^^^^ # Reads from stdin. 34 # ^^^^^^^^^^ # Writes to stdout. 35 # However, both stdin and stdout were redirected. 36 # ----------------------------------------------- 37 38 exec 1>&7 7>&- # Restore stout. 39 exec 0<&4 4<&- # Restore stdin. 40 41 # After restoration, the following line prints to stdout as expected. 42 echo "File \"$1\" written to \"$2\" as uppercase conversion." 43 44 exit 0
Notes
[1] A file descriptor is simply a number that the operating system assigns to an open file to keep track of it. Consider it a simplified version of a file pointer. It is analogous to a file handle in C. [2] Using file descriptor 5 might cause problems. When Bash creates a child process, as with exec, the child inherits fd 5 (see Chet Ramey's archived e-mail, SUBJECT: RE: File descriptor 5 is held open). Best leave this particular fd alone.
Q: According to the many sources the exec command other than its use in find and escaping the shell, has another definitive use.. which I am having a hard time understanding.
according to many resources and info pages that I have read I can use the exec command with a file descriptor.. such as
exec 1< file
or
exec 5>&0
I do not quite understand what a file descriptor is and what is the purpose of this (pattern) or (expression)..
any feedback welcomeA: If you write a script, you can send input into it like this:
./somescript < inputfile
The script can accomplish the same thing internally by using:
exec < inputfile
After that line, the script's input is inputfile. It can do the same to output:
exec > somescript.log 2>&1
This send stderr and stdout combined into the file. There is more to it, but this is the basics.
Hey There,
Simply put, fork duplicates your shell (file descriptors, etc) in a subshell. Usually a forked process will then exec in that subshell.
exec exec's the command in your current shell, basically co-opting it.
In pure versions of exec, if you do, just at the shell prompt:
exec khs <-- instead of exec ksh
your shell will be replaced by khs, which doesn't exist, and you'll lose your shell (get logged out).
Redhat, OpenSolaris, and most Linux brands do a "fake exec" (really a fork and then exec) now, where, even when you call exec and flub it, you don't lose your shell.
Not a very technical explanation, but hopefully helpful
, Mike
Sys Admin v16, i03
As Sys Admin contributing editors, we've had the opportunity to answer a number of novice shell questions. In this column, we'll cover a few of the questions we've been asked:
- Using the exec and eval commands
- Combining files using the paste command
- Processing a string a character at a time
- Deleting a file named dash
Using the exec & eval Commands
One novice asked when it was suitable to exec and eval Unix commands:
exec mycommand eval mycommandThe exec command works differently depending on the shell; in the Bourne and Korn shells, the exec command replaces the current shell with the command being exec'ed. Consider this stub script:exec echo "Hello John" echo "Hello Ed" # end stubWhen the above stub executes, the current shell will be replaced when exec'ing the echo "Hello John" command. The echo "Hello Ed" command never gets the chance to execute. Obviously, this capability has limited uses.You might design a shell menu where the requirement is to execute an option that never returns to the menu. Another use would be restricting the user from obtaining the command line. The following last line in the user's .profile file logs the user out as soon as my_executable terminates:
exec my_executableHowever, most systems administrators probably use the exit command instead:my_executable exitDon't confuse exec'ing a Unix command with using exec to assign a file to a file descriptor. Remember that the default descriptors are standard input, output, and error or 0, 1, and 2, respectively.Let's consider an example where you need to read a file with a while loop and ask the user for input in the same loop. Assign the file to an unused descriptor -- 3 in this case -- and obtain the user input from standard input:
exec 3< file.txt while read line <&3 do echo "$line" echo "what is your input? " read answer . . done exec 3<&- # close the file descriptor when doneThe eval command is more interesting. A common eval use is to build a dynamic string containing valid Unix commands and then use eval to execute the string. Why do we need eval? Often, you can build a command that doesn't require eval:evalstr="myexecutable" $evalstr # execute the command stringHowever, chances are the above command won't work if "myexecutable" requires command-line arguments. That's where eval comes in.Our man page says that the arguments to the eval command are "read as input to the shell and the resulting commands executed". What does that mean? Think of it as the eval command forcing a second pass so the string's arguments become the arguments of the spawned child shell.
In a previous column, we built a dynamic sed command that skipped 3 header lines, printed 5 lines, and skipped 3 more lines until the end of the file:
evalstr="sed -n '4,\${p;n;p;n;p;n;p;n;p;n;n;n;}' data.file" eval $evalstr # execute the command stringThis command fails without eval. When the sed command executes in the child shell, eval forces the remainder of the string to become arguments to the child.Possibly the coolest eval use is building dynamic Unix shell variables. The following stub script dynamically creates shell variables user1 and user2 setting them equal to the strings John and Ed, respectively:
COUNT=1 eval user${COUNT}=John echo $user1 COUNT=2 eval user${COUNT}=Ed echo $user2 Pasting Files with pasteAnother novice asked how to line up three files line by line sending the output to another file. Given the following:file1: 1 2 3 file2: a b c file3: 7 8 9the output file should look like this:1a7 2b8 3c9The paste command is a ready-made solution:paste file1 file2 file3By default, the delimiter character between the columns is a tab key. The paste command provides a -d delimiter option. Everything after -d is treated as a list. For example, this paste rendition uses the pipe symbol and ampersand characters as a list:paste -d"|&" file1 file2 file3The command produces this output:1|a&7 2|b&8 3|c&9The pipe symbol character, |, is used between columns 1 and 2, while the ampersand, &, separates column 2 and 3. If the list is completely used, and if the paste command contains more files arguments, then paste starts at the beginning of the list.To satisfy our original requirement, paste provides a null character, \0, signifying no character. To prevent the shell from interpreting the character, it must also be quoted:
paste -d"\0" file1 file2 file3
The exec command will replace the parent process by whatever the command is typed.
Try the following:
exec ls -lAs you will have noticed, this closes the shell you are currently using. Why?
The exec command terminated the parent process and started (executed) the ls command and the ls command did what it was supposed to do and exited with a zero status, but ls has no parent process to return to, and thereby the shell is shut down.
If for example, we ran our eatout.sh script, but instead of running it as we have previously, we exec'd it, the script would run but would also close our terminal from which we ran the script.
exec eatout.shThis means that when the person finally types exit to exit the menu, they are sent back to the login prompt.
To see this in action, let's consider the following sequence of commands:
pstree -p |lessYou will notice that "pstree" starts with the init command or the init process. Somewhere further down this 'tree', init starts a shell (bash/ksh/csh) which is then going to run the pstree and the less command.
Now, in order to see exec at work, we need to find out the current process id.
Use:
echo $$to determine this (the ps command would give you the same information).
Now type the pstree command again, producing a diagram of your process tree.
pstree -p | lessSearch for your process id recorded from the echo above. Once you have located it, quit pstree and type:
exec bashThis would replace our current shell (our parent) with a new shell, and thus a new process id (PID).
echo $$You can also look at the pstree again.
By using the exec command, instead of making the new shell's parent your original shell, the new shell will be owned by init.
45.7 The exec CommandThe exec command will execute a command in place of the current shell; that is, it terminates the current shell and starts a new process (38.3) in its place.
Historically, exec was often used to execute the last command of a shell script. This would kill the shell slightly earlier; otherwise, the shell would wait until the last command was finished. This practice saved a process and some memory. (Aren't you glad you're using a modern system? This sort of conservation usually isn't necessary any longer unless your system limits the number of processes each user can have.)
exec can be used to replace one shell with another shell:
%exec kshwithout incurring the additional overhead of having an unused shell waiting for the new shell to finish.
exec also manipulates file descriptors (45.21, 45.22) in the Bourne shell. When you use exec to manage file descriptors, it does not replace the current process. For example, the following command makes the standard input of all commands come from the file formfile instead of the default place (usually, your terminal):
exec < formfile- ML, JP
|
|
||||
| Bulletin | Latest | Past week | Past month |
|
Most popular humor pages:
Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : C++ Humor : ARE YOU A BBS ADDICT? : Object oriented programmers of all nations : C Humor : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor: Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : The Most Comprehensive Collection of Editor-related Humor : Microsoft plans to buy Catholic Church : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor : Best Russian Programmer Humor : Russian Musical Humor : The Perl Purity Test : Politically Incorrect Humor : GPL-related Humor : OFM Humor : IDS Humor : Real Programmers Humor : Scripting Humor : Web Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor :
Copyright © 1996-2013 by Dr. Nikolai Bezroukov. www.softpanorama.org was created as a service to the UN Sustainable Development Networking Programme (SDNP) in the author free time. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Site uses AdSense so you need to be aware of Google privacy policy. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine. This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...
|
|
You can use PayPal to make a contribution, supporting hosting of this site with different providers to distribute and speed up access. Currently there are two functional mirrors: softpanorama.info (the fastest) and softpanorama.net. |
Disclaimer:
The statements, views and opinions presented on this web page are those of the author and are not endorsed by, nor do they necessarily reflect, the opinions of the author present and former employers, SDNP or any other organization the author may be associated with. We do not warrant the correctness of the information provided or its fitness for any purpose.
Last modified: January 27, 2013