Two exec commands in one shell script?


 
Thread Tools Search this Thread
Top Forums UNIX for Beginners Questions & Answers Two exec commands in one shell script?
# 1  
Old 02-12-2019
Two exec commands in one shell script?

Hi Folks -


Is there a way to add two execs to one script? For instance, I need to redirect the stdout and stderr to two separate directories. I want to do this:
Code:
#::-- Direct STDOUT and STDERROR to repositories --::# 
exec 2>"${_ERRORFILE}" > "${_LOGFILE}"
exec 2>"/new/path/file.err" > "/new/path/file.log"


But obviously only the last exec is being used. Any tricks?



Thanks!
# 2  
Old 02-12-2019
What's your OS and shell versions?
# 3  
Old 02-12-2019
HI RudiC-


Code:
  GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

Thanks!

Last edited by RudiC; 02-12-2019 at 02:13 PM..
# 4  
Old 02-12-2019
With that bash version, providing "process substitution", this might work for you:


Code:
exec > >(tee ZZ > XX) 2> >(tee ZZZ > XXX)

This User Gave Thanks to RudiC For This Post:
# 5  
Old 02-12-2019
Quote:
Originally Posted by SIMMS7400
Is there a way to add two execs to one script? For instance, I need to redirect the stdout and stderr to two separate directories. I want to do this:
Code:
#::-- Direct STDOUT and STDERROR to repositories --::# 
exec 2>"${_ERRORFILE}" > "${_LOGFILE}"
exec 2>"/new/path/file.err" > "/new/path/file.log"


But obviously only the last exec is being used. Any tricks?
Actually there are - but not using exec. Let me first explain the use of exec, then what you can do to fulfill your requirement.

The keyword exec is used for two very different purposes: the first is to replace (instead of fork) the current process. Consider this script part:

Code:
command1
command2

What happens when the shell executes this is:

1) create a subprocess and start command1 in this
2) wait until this subprocess has finished
3) create another subprocess and start command2 in it
etc..

As long as it takes i.e. command1 to run you would see the process of your script (say, yourscript.sh) in the process list as parent process and command1 as child process. exec instead will replace the running script (effectively stopping its execution) with the command in question, which will take over the process number and everything else of the - up to now - running script. That means:

Code:
exec command1
command2

would be pointless because after the first line being executed the script is not running any more and hence command2 will never be executed. So, in this sense, two exec in one script would not make sense - except, of course, if there is some condition attached to it:

Code:
if <condition> ; then
     exec command1
else
     exec command2
fi

The second purpose - without any command but a redirection instead - of exec is to redirect I/O as you have done. The problem regarding your goal is not so much exec itself but a property of UNIX processes: processes have (per default) one input - <stdin> - and two outputs: <stdout> and <stderr>. Any of these "I/O descriptors", as the correct wording is, can point to any source providing a data stream: a file, a device, a pipeline, ... exec > /some/where is just a fancy way of directing the <stdout> I/O descriptor to that certain file.

You can use several such execs to re-redirect these streams to various sources/targets, but each such redirection will overwrite the previous one. Not because of the way exec works, but because each I/O-descriptor can either point this way or that way, but not both. Picture a UNIX process as a sort-of garden hose: you fill something in at one end and something comes out on the other. You can use what comes out to fill this bucket or that bucket, but not both at the same time.

For such a thing - to fill both buckets at the same time - you would need a "T-piece", as plumbers call it: something to divide the water stream into two water streams. Exactly this analogy inspired the makers of UNIX to create the tee utility. You can use it to duplicate an output stream so that it will go to two different targets at the same time. You cannot use that inside the script but you can use it outside with a redirection:

Code:
yourscript.sh | tee /some/file >/other/file

will write <stdout> of yourscript.sh to both /some/file and /other/file. I suggest you read the man page of tee to get acquainted. If you still need help just ask.

I hope this helps.

bakunin
# 6  
Old 02-12-2019
Hi Rudi -


That worked great!!! I do have one additional follow up. I also use a trap command to remove the error file and error directory (if empty) at the end as with exec, they need to be created first.



My current trap is only working for what I have speicfic. How would I add in the a second trap statement? Do I need to do this in a function?



Code:
#!/bin/bash
#::--:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#::-- Script Name: CFPBCSDDI.sh                                               --::
#::                                                                           --::
#::-- Description: Executes Cloud Artifact Snapshot Backup                    --::
#::                                                                                                                                                                                                                                                                                     --::
#::                                                                                                                                                                                                                                                                                     --::
#::                                                                                                                                                                                                                                                                                                 --::
#::--  Calls:      _env.sh                                                    --::
#::--  Called By:  N/A                                                        --::
#::                                                                                                                                                                                                                                                           --::
#::-- Parameters:  Not Applicable                                                                                                                                                                                 --::
#::                                                                                                                                                                                                                                                           --::
#::-- Author:      XXX                                                                                                             --::
#::-- Date:                   12/31/17                                                                       --::
#::                                                                                                                                                                                                                                                                                                 --::
#::--:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

#::-- Set Environment File --::#
source "$PWD/_env_DDI.sh"

#::-- Prepare File Name Format --::#
#::   _SN          = Script Name with extension
#::   ${_SN%%.sh*} = Script name without extension
#::   _FN          = File Name

_SN="${0##*/}"
_FN="${_DATESTAMP}_${_TIME}_${_SN%%.sh*}"

#::-- Set Log & Error subdirectories pertaining to the specific process --::#
_PLOGPATH="${_SN%%.sh*}_Logs/"
_PERRORPATH="${_SN%%.sh*}_Errors/"

#::-- Establish STDOUT and STDERROR repositories --::
_INTRAPATH="${_LOGPATH}${_PLOGPATH}${_YEAR}_${_MONTH}${_DAY}"
_ERRORINTRAPATH="${_ERRORPATH}${_PERRORPATH}${_YEAR}_${_MONTH}${_DAY}"

for _DIR in "${_INTRAPATH}" "${_ERRORINTRAPATH}"; do mkdir -m777 -p "${_DIR}"; done

#::-- Establish STDOUT and STDERROR files --::#
_LOGFILE="${_INTRAPATH}/${_FN}.log"
_ERRORFILE="${_ERRORINTRAPATH}/${_FN}.err"

#::-- Direct STDOUT and STDERROR to repositories --::# 
#exec 2>"${_ERRORFILE}" > "${_LOGFILE}"

_CTRLM_OUTPUT="/cfit/ctrlm/dev/links/logs"
exec > >(tee "${_CTRLM_OUTPUT}/${_FN}.log" > "${_LOGFILE}") 2> >(tee "${_CTRLM_OUTPUT}/${_FN}.err" > "${_ERRORFILE}")

#::-- Delete YYYY_MMDD error file subdirectory if empty --::
trap "[ -s ${_ERRORFILE} ] || rm -f ${_ERRORFILE} && rmdir ${_ERRORINTRAPATH}" EXIT

#::-- Additional Variable Assignment --::#  

_SNAPSHOT="Artifact Snapshot"
_TARGETPATH="${_BACKUPPATH}${_SNAPSHOT}"; mkdir -m777 -p "${_TARGETPATH}"
_CNT="0"

#::--------------------Initialize Functions--------------------------::#




Moderator's Comments:
Mod Comment Please use CODE tags as required by forum rules!

Last edited by RudiC; 02-12-2019 at 02:15 PM.. Reason: Changed QUOTE to CODE tags.
# 7  
Old 02-12-2019
Quote:
Originally Posted by SIMMS7400
I also use a trap command to remove the error file and error directory (if empty) at the end as with exec, they need to be created first.

My current trap is only working for what I have speicfic. How would I add in the a second trap statement?
A trap is code which is executed when a script receives a certain signal (like, via the kill command or via the keyboard, i.e. pressing <CTRL>-<C>). Since each signal can only have one reaction attached to it you cannot specify two traps for the same signal although you can specify traps for different signals.

Notice that - depending on your shell - there might also be a "pseudo-signal" raised when leaving a script via the normal exit. This is no real signal at all but it can be trapped the same way any other signal can. In bash this is done like this:

Code:
#! /bin/bash

function myexit
{
<put all that needs to be executed upon exit here>
}

# main code starts here:
trap myexit EXIT
<rest of your code>

The function myexit() will be executed when the script is left through the exit command.

I hope this helps.

bakunin
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Run 2 exec commands

I have to create two instances of jBoss 5.1.0 GA. In order to do that I have to execute the following in start-jboss.sh: find . -exec /opt/novell/idm/jboss/bin/run.sh -Djboss.service.binding.set=ports-01 -c IDMProv -b 0.0.0.0 \; -exec /opt/novell/idm/jboss/bin/run.sh... (4 Replies)
Discussion started by: Joydeep Ghosh
4 Replies

2. UNIX for Dummies Questions & Answers

Using find -exec with multiple commands :(-

Hi all, Am wanting to do a ls -l of the files and do a cat of it at the same time, ideally, I am hoping that the following work but obvisouly it is not working to what I am wanting it to ... hu hu hu :wall: find . -name "BACKUP_TIMESTAMP.log" -exec "ls -l basename {} ; cat {}" \; ... (1 Reply)
Discussion started by: newbie_01
1 Replies

3. Shell Programming and Scripting

Script Variables Inquiry, Values Okay in Standalone Exec, No-Show in Cron Exec

I have the following bash script lines in a file named test.sh. #!/bin/bash # # Write Date to cron.log # echo "Begin SSI Load $(date +%d%b%y_%T)" # # Get the latest rates file for processing. # d=$(ls -tr /rms/data/ssi | grep -v "processed" | tail -n 1) filename=$d export filename... (3 Replies)
Discussion started by: ginowms
3 Replies

4. UNIX for Advanced & Expert Users

find -exec with 2 commands doesn't work (error incomplete staement)

Hi Gurues, I need to modify an existing script that uses find to search a folder, and then move its contents to a folder. What I need to do is run gzip on each file after it's moved. So, I ran this little test: Put a ls.tar file on my $HOME, mkdir tmp, and then: virtuo@tnpmprd01: find .... (3 Replies)
Discussion started by: llagos
3 Replies

5. UNIX for Dummies Questions & Answers

How to run multiple piped commands in a find -exec statement?

I can't get this to work. Running a single command works fine: find . -name "*.dat" -exec wc -l '{}' \; gives me the file name and number of lines in each .dat file in the directory. But what if I want to pipe commands, e.g. to grep something and get the number of lines with that pattern... (3 Replies)
Discussion started by: DJR
3 Replies

6. UNIX for Dummies Questions & Answers

How to run two commands from a exec call in a c program

Hi, I have to run two commands one after another from a c program. How can i do this with exec system calls. i tried giving them as argument to execv but it is not working.please help thanks (3 Replies)
Discussion started by: suryashikha
3 Replies

7. Shell Programming and Scripting

Why can't embed commands like fg or bg in a shell script ?

Hi Can someone explain in an easy way that why can't embed commands like fg or bg in a shell script ? (4 Replies)
Discussion started by: qiulang
4 Replies

8. Shell Programming and Scripting

How to run unix commands in a new shell inside a shell script?

Hi , I am having one situation in which I need to run some simple unix commands after doing "chroot" command in a shell script. Which in turn creates a new shell. So scenario is that - I need to have one shell script which is ran as a part of crontab - in this shell script I need to do a... (2 Replies)
Discussion started by: hkapil
2 Replies

9. Shell Programming and Scripting

Exec. commands in python

How would i do if i'd want to execute a command in a python script or programme ? (1 Reply)
Discussion started by: J.P
1 Replies
Login or Register to Ask a Question