LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-01-2014, 01:01 AM   #1
budgie26
LQ Newbie
 
Registered: Nov 2012
Posts: 17

Rep: Reputation: Disabled
Copy not redirect stdout and stderr in bash


I'm converting a script from csh to bash for use with a PBS batch job system, and I need to add commands which redirect stdout and stderr (hence the conversion to bash). What I'm after is not a simple case of using:
Code:
command_to_run $1 $2 $3 1> output.log 2> error.log
as I need to COPY the stdout and stderr to files and not just redirect.

My script processes multiple files via a single PBS batch job. Each file needs to have its own output and error log file (which the above code will do), but the single PBS job also needs to have the stdout and stderr output for each processed file put into its own output and error log file. The PBS batch job system uses stdout for its output log file and stderr for its error log file. I need to use the PBS error log file to check for any errors in the processed files, rather than going into each file's error log file (I'm dealing with thousands of files!). I don't want to have to create a separate script to consolidate the errors into a new file if the PBS error log file can provide this information with a small amount of coding.

I've done lots of searching to solve this but haven't had any luck. I'm new to bash, so it may be a case of me not fully understanding the coding.

What I require is:
1. copy the stdout results to 'output.log' for each processed file and keep the results in stdout so it can be picked up by the PBS batch job output results file.
2. copy the stderr results to 'error.log' for each processed file and keep the results in stderr so it can be picked up by the PBS batch job error results file.

Is there a way to have the std* go to both the *.log file and to the PBS log file?

In addition, I need to record the command line and arguments to a 'command_log' file. This currently happens with the csh file, but I can't work out the coding in bash. The csh script has the command:
Code:
alias GM 'echo \!* | tee -a log; echo; \!* >>! log1'
GM command_to_run $1 $2 $3
The alias GM is put before the commands I want to capture and enables the command line input and arguments to be put into the 'log' file and the stdout into the 'log1' file. All I want is to capture what's in the 'log' file.

Any advice would be greatly appreciated!!

Thanks in advance
 
Old 05-01-2014, 03:24 AM   #2
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Well I am not sure I exactly follow, however, the tee command from your csh example is what would be used to have output streamed to 2 separate locations (i think this is what you are asking)

As for the alias, I think you need to create a function as opposed to an alias (I could be wrong but am not familiar with '!*'):
Code:
GM()
{
  echo $* | tee -a log
  echo
  $* >> log1
}
 
Old 05-01-2014, 04:47 AM   #3
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
bash only:
Code:
command >(tee output.log) 2>(tee error.log)
to log commands:
Code:
set -vx

Last edited by NevemTeve; 05-01-2014 at 04:50 AM.
 
Old 05-04-2014, 09:16 PM   #4
budgie26
LQ Newbie
 
Registered: Nov 2012
Posts: 17

Original Poster
Rep: Reputation: Disabled
Thanks. I found that NevemTeve's suggestions didn't work, but I've found that doing the following gets me closer to a suitable solution:

Code:
GM()
{
    echo $* | tee -a command.log
    echo
    $* >> output.log
}
This gives me the command and output details I want in the relevent files, but I can't get stderr to the error.log to work within this function. I've tried adding:

Code:
2> error.log
cat error.log 1>&2
But this doesn't work, as the error.log file is blank. Any ideas?
 
Old 05-04-2014, 10:25 PM   #5
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
> I found that NevemTeve's suggestions didn't work

What did you try? Did you get an error message? Or what happened?
...

Code:
2> error.log
cat error.log 1>&2
> But this doesn't work, as the error.log file is blank. Any ideas?

What should have happened?
 
Old 05-04-2014, 10:40 PM   #6
budgie26
LQ Newbie
 
Registered: Nov 2012
Posts: 17

Original Poster
Rep: Reputation: Disabled
'set -vx' printed all the commands within the script,instead of just the single command line I'm interested in (eg. command $1 $2) within the script. When I did 'command >(tee output.log) 2>(tee error.log)' these files were empty and I didn't get any errors.

When I tried:

Code:
GM()
{
    echo $* | tee -a command.log
    echo
    $* >> output.log
    2> error.log
    cat error.log 1>&2
}
The command.log file shows the single command line I'm interested in, the output.log file has the stdout details but the error.log file is empty. The PBS job shows the stderr, so it looks like the errors haven't been piped to the error.log file and then copied back to the stderr.

If I run:

Code:
command $1 $2 1> output.log 2> error.log
cat error.log 1>&2
cat output.log
The output.log and error.log files have the right details, and the stderr and stdout are still piped to the PBS job output files. This provides everything I want except for the command.log. I'm not keen on this solution as it doesn't have the command.log details and I'd have to manually write the redirections and cat commands after each command in the script. Having a function instead would be much easier as there are quite a few commands in the script.
 
Old 05-04-2014, 11:52 PM   #7
SaintDanBert
Senior Member
 
Registered: Jan 2009
Location: "North Shore" Louisiana USA
Distribution: Mint-20.1 with Cinnamon
Posts: 1,771
Blog Entries: 3

Rep: Reputation: 108Reputation: 108
Quote:
Originally Posted by NevemTeve View Post
> I found that NevemTeve's suggestions didn't work
What did you try? Did you get an error message? Or what happened?
...
Code:
2> error.log
cat error.log 1>&2
But this doesn't work, as the error.log file is blank. Any ideas?
What should have happened?
As I understand things 1>&2 says to direct output on "channel 1" (STDOUT) onto "channel 2" (STDERR)?

Don't you want to send STDERR to STDOUT instead as 2>&1?

~~~ 0;-Dan
 
Old 05-04-2014, 11:57 PM   #8
budgie26
LQ Newbie
 
Registered: Nov 2012
Posts: 17

Original Poster
Rep: Reputation: Disabled
No I want send stdout to stderr (1>&2). By doing 'cat error.log 1>&2' this will display the error.log contents as an output not an error, so I want to redirect the contents of error.log back to stderr.
 
Old 05-05-2014, 01:57 AM   #9
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,842

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
to copy means (at least for me) to duplicate. The normal stdout (and stderr) should be saved and printed too. In that case you may try to use screen -L <your command> (this will mix stdout and stderr, but save it), or you can try to solve it with tee.
The redirection like:
Code:
2>error.log
cat error.log 1>&2
will not work, because the first line will just create an empty error.log file and the second line will immediately print it (and of course it is completed). Redirection to error.log may work, but the cat command already finished.

Here is a small example, probably it can be used:
Code:
mkfifo /tmp/fifo.stdout
cat /tmp/fifo.stdout | tee /tmp/stdout.log
mkfifo /tmp/fifo.stderr
cat /tmp/fifo.stderr | tee /tmp/stderr.log

your_command >/tmp/fifo.stdout 2>/tmp/fifo.stderr
this will save stdout and stderr in /tmp and also print
 
1 members found this post helpful.
Old 05-05-2014, 02:47 AM   #10
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
Ok, I was plain wrong. Now it is tested:
Code:
#!/bin/bash
./command_that_writes_stdout_and_stderr \
	 > >(tee output.log) 		\
	2> >(tee error.log >&2)
 
Old 05-05-2014, 03:31 AM   #11
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
As pointed out by pan64, if you wish to redirect stderr, you will need to do this at the point of calling the command, ie. not after:
Code:
GM()
{
    echo $* | tee -a command.log
    echo
    $* >> output.log 2> error.log
    
    cat error.log 1>&2  # I was not sure of the purpose of this line so left as is
}
 
Old 05-07-2014, 08:47 PM   #12
budgie26
LQ Newbie
 
Registered: Nov 2012
Posts: 17

Original Poster
Rep: Reputation: Disabled
Thank you for all your help, I now have the solution!

Code:
GM()
{
    echo $* | tee -a command.log
    echo
    $* >> output.log 2> error.log
    cat error.log 1>&2
}
This will create three files (command.log, output.log, error.log) for each processed file as well as copy the stdout and stderr to the PBS job output files.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
TCSH: redirect stdout and stderr seperately ugenn Linux - General 3 02-07-2016 03:23 PM
Redirect stdout/stderr of multiple commands in one shot veeruk101 Linux - Newbie 1 06-03-2011 08:02 AM
Cannot redirect all stdout and stderr into file hawkgao Programming 2 05-12-2009 09:14 AM
Perl stderr&stdout redirect question Fredde87 Programming 5 03-26-2009 04:43 AM
How to redirect standard stdout to multi stdout ( Bash )? john.daker Programming 4 11-03-2008 11:20 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:22 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration