Skip to main content
added 500 characters in body
Source Link
vladr
  • 67k
  • 18
  • 131
  • 132
sub setEnvironment() { if ( fileno OUT ) { unless ( open(STDOUT, ">&OUT") ) { print "Cannot redirectrestore STDOUT"; return 2; } unless ( open(STDERR, ">&ERR") ) { print "Cannot redirectrestore STDERR"; return 2; } } else { unless ( open(OUT, ">&STDOUT") ) { print "Cannot redirect STDOUT"; return 2; } unless ( open(ERR, ">&STDERR") ) { print "Cannot redirect STDERR"; return 2; } } unless ( open(STDOUT, "|tee -ai $g_LOGPATH/$g_LOGFILE") ) ... 

Why and how does this work? We simply want to temporarily restore the original STDOUT immediately before rewiring it into tee, so that tee inherits ittemporarily restore the original STDOUT immediately before rewiring it into tee, so that tee inherits it as its standard output and actually writes directly to the original STDOUT (e.g. your terminal) instead of writing (in the case of the forked children) through the parent's tee (which is where the child's STDOUT normally pointspointed to before this change, by virtue of inheriting from the paremnt process, and which is what injected those child lines into parent.log.) In

So in answer to one of your questions, whoever wrote the code to set OUT and ERR must have had exactly the above in mind. (I cannot help but wonder whether or not the difference in indentation in your original code is indicative of someone having removed, in the past, code similar to the one you have to add back now.)

sub setEnvironment() { if ( fileno OUT ) { unless ( open(STDOUT, ">&OUT") ) { print "Cannot redirect STDOUT"; return 2; } unless ( open(STDERR, ">&ERR") ) { print "Cannot redirect STDERR"; return 2; } } else { unless ( open(OUT, ">&STDOUT") ) { print "Cannot redirect STDOUT"; return 2; } unless ( open(ERR, ">&STDERR") ) { print "Cannot redirect STDERR"; return 2; } } unless ( open(STDOUT, "|tee -ai $g_LOGPATH/$g_LOGFILE") ) ... 

Why and how does this work? We simply want to temporarily restore the original STDOUT immediately before rewiring it into tee, so that tee inherits it and actually writes directly to the original STDOUT (e.g. your terminal) instead of writing (in the case of the children) through the parent's tee (which is where the child's STDOUT normally points to before this change, by virtue of inheriting from the paremnt process, and which is what injected child lines into parent.log.) In answer to one of your questions, whoever wrote the code to set OUT and ERR must have had exactly the above in mind.

sub setEnvironment() { if ( fileno OUT ) { unless ( open(STDOUT, ">&OUT") ) { print "Cannot restore STDOUT"; return 2; } unless ( open(STDERR, ">&ERR") ) { print "Cannot restore STDERR"; return 2; } } else { unless ( open(OUT, ">&STDOUT") ) { print "Cannot redirect STDOUT"; return 2; } unless ( open(ERR, ">&STDERR") ) { print "Cannot redirect STDERR"; return 2; } } unless ( open(STDOUT, "|tee -ai $g_LOGPATH/$g_LOGFILE") ) ... 

Why and how does this work? We simply want to temporarily restore the original STDOUT immediately before rewiring it into tee, so that tee inherits it as its standard output and actually writes directly to the original STDOUT (e.g. your terminal) instead of writing (in the case of the forked children) through the parent's tee (which is where the child's STDOUT normally pointed to before this change, by virtue of inheriting from the paremnt process, and which is what injected those child lines into parent.log.)

So in answer to one of your questions, whoever wrote the code to set OUT and ERR must have had exactly the above in mind. (I cannot help but wonder whether or not the difference in indentation in your original code is indicative of someone having removed, in the past, code similar to the one you have to add back now.)

added 500 characters in body
Source Link
vladr
  • 67k
  • 18
  • 131
  • 132

If it is important to achieve both 1. and 2. above, then take your original code and simply add a methodthe following at the top of your setEnvironment method:

sub restoreEnvironmentsetEnvironment() {   if ( fileno OUT ) { unless ( open(STDOUT, ">&OUT") )   {   print "Cannot restoreredirect STDOUT";   return 2;   }   unless ( open(STDERR, ">&ERR") )   {   print "Cannot restoreredirect STDERR";   return 2;   } close}  OUT; else close{  ERR; unless ( open(OUT, ">&STDOUT") ) { print "Cannot redirect STDOUT"; return 2; } unless ( open(ERR, ">&STDERR") ) { print "Cannot redirect STDERR";  return 2; }  } unless ( open(STDOUT, "|tee -ai $g_LOGPATH/$g_LOGFILE") ) ... 

then call setEnvironment(); once before the while loop, and call restoreEnvironment(); inside the while, but before the fork (incidentallyIncidentally, do not forget to also add $pid to @pids if your actual code does not do that already):

. .. $g_LOGFILE="parent.log"; setEnvironment(); while ($file = readdir(DIR)) { restoreEnvironment(); my $pid = fork; if ( $pid ) { push @pids, $pid; ... 

Why and how does this work? We simply want to temporarily restore the original STDOUT immediately before forkingrewiring it into tee, so that the child's tee inherits it and actually writes directly to the original STDOUT (e.g. your terminal) instead of writing (in the case of the children) through the parent's tee (which is where the child's STDOUT normally points to before this change, by virtue of inheriting from the paremnt process, and which is what injected child lines into parent.log.) In answer to one of your questions, whoever wrote the code to set OUT and ERR must have had exactly the above in mind.

If it is important to achieve both 1. and 2. above, then take your original code and simply add a method:

sub restoreEnvironment() { unless ( open(STDOUT, ">&OUT") ) { print "Cannot restore STDOUT"; return 2; } unless ( open(STDERR, ">&ERR") ) { print "Cannot restore STDERR"; return 2; } close OUT; close ERR; } 

then call setEnvironment(); once before the while loop, and call restoreEnvironment(); inside the while, but before the fork (incidentally, do not forget to also add $pid to @pids if your actual code does not do that already):

... $g_LOGFILE="parent.log"; setEnvironment(); while ($file = readdir(DIR)) { restoreEnvironment(); my $pid = fork; if ( $pid ) { push @pids, $pid; ... 

Why and how does this work? We simply want to temporarily restore the original STDOUT before forking, so that the child's tee actually writes directly to the original STDOUT (e.g. your terminal) instead of writing through the parent's tee (which is what injected child lines into parent.log.) In answer to one of your questions, whoever wrote the code to set OUT and ERR must have had exactly the above in mind.

If it is important to achieve both 1. and 2. above, then take your original code and simply add the following at the top of your setEnvironment method:

sub setEnvironment() {   if ( fileno OUT ) { unless ( open(STDOUT, ">&OUT") )   {   print "Cannot redirect STDOUT";   return 2;   }   unless ( open(STDERR, ">&ERR") )   {   print "Cannot redirect STDERR";   return 2;   } }   else {   unless ( open(OUT, ">&STDOUT") ) { print "Cannot redirect STDOUT"; return 2; } unless ( open(ERR, ">&STDERR") ) { print "Cannot redirect STDERR";  return 2; }  } unless ( open(STDOUT, "|tee -ai $g_LOGPATH/$g_LOGFILE") ) ... 

Incidentally, do not forget to also add $pid to @pids if your actual code does not do that already:

 ... my $pid = fork; if ( $pid ) { push @pids, $pid; ... 

Why and how does this work? We simply want to temporarily restore the original STDOUT immediately before rewiring it into tee, so that tee inherits it and actually writes directly to the original STDOUT (e.g. your terminal) instead of writing (in the case of the children) through the parent's tee (which is where the child's STDOUT normally points to before this change, by virtue of inheriting from the paremnt process, and which is what injected child lines into parent.log.) In answer to one of your questions, whoever wrote the code to set OUT and ERR must have had exactly the above in mind.

added 500 characters in body
Source Link
vladr
  • 67k
  • 18
  • 131
  • 132

It would appear that the intent of the original code is as follows:

  1. when the script is started from, say, a terminal, then provide aggregate parent and child output to the terminal
  2. additionally, provide a copy of the parent output in parent.log, and a copy of child output in child.log

Note that @Unk's answer is correct as far as 2. goes, and has less moving parts than any code using tee, but fails to achieve 1.

If it is important to achieve both 1. and 2. above, then take your original code and simply add a method:

sub restoreEnvironment() { unless ( open(STDOUT, ">&OUT") ) { print "Cannot restore STDOUT"; return 2; } unless ( open(STDERR, ">&ERR") ) { print "Cannot restore STDERR"; return 2; } close OUT; close ERR; } 

then call setEnvironment(); once before the while loop, and call restoreEnvironment(); inside the while, but before the fork (incidentally, do not forget to also add $pid to @pids if your actual code does not do that already):

... $g_LOGFILE="parent.log"; setEnvironment(); while ($file = readdir(DIR)) { restoreEnvironment(); my $pid = fork; if ( $pid ) { push @pids, $pid;   ... 

Why and how does this work? We simply want to temporarily restore the original STDOUT before forking, so that the child's tee actually writes directly to the original STDOUT (e.g. your terminal) instead of writing through the parent's tee (which is what injected child lines into parent.log.) In answer to one of your questions, whoever wrote the code to set OUT and ERR must have had exactly the above in mind.

Here's what you now get at the end of the day:

$ rm -f parent.log child.log $ perl test.pl child parent child parent parent child parent child parent $ cat parent.log parent parent parent parent parent $ cat child.log child child child child child 

It would appear that the intent of the original code is as follows:

  1. when the script is started from, say, a terminal, then provide aggregate parent and child output to the terminal
  2. additionally, provide a copy of the parent output in parent.log, and a copy of child output in child.log

Note that @Unk's answer is correct as far as 2. goes, and has less moving parts than any code using tee, but fails to achieve 1.

If it is important to achieve both 1. and 2. above, then take your original code and simply add a method:

sub restoreEnvironment() { unless ( open(STDOUT, ">&OUT") ) { print "Cannot restore STDOUT"; return 2; } unless ( open(STDERR, ">&ERR") ) { print "Cannot restore STDERR"; return 2; } close OUT; close ERR; } 

then call setEnvironment(); once before the while loop, and call restoreEnvironment(); inside the while, but before the fork:

... $g_LOGFILE="parent.log"; setEnvironment(); while ($file = readdir(DIR)) { restoreEnvironment(); my $pid = fork; ... 

Why and how does this work? We simply want to temporarily restore the original STDOUT before forking, so that the child's tee actually writes directly to the original STDOUT (e.g. your terminal) instead of writing through the parent's tee (which is what injected child lines into parent.log.) In answer to one of your questions, whoever wrote the code to set OUT and ERR must have had exactly the above in mind.

It would appear that the intent of the original code is as follows:

  1. when the script is started from, say, a terminal, then provide aggregate parent and child output to the terminal
  2. additionally, provide a copy of the parent output in parent.log, and a copy of child output in child.log

Note that @Unk's answer is correct as far as 2. goes, and has less moving parts than any code using tee, but fails to achieve 1.

If it is important to achieve both 1. and 2. above, then take your original code and simply add a method:

sub restoreEnvironment() { unless ( open(STDOUT, ">&OUT") ) { print "Cannot restore STDOUT"; return 2; } unless ( open(STDERR, ">&ERR") ) { print "Cannot restore STDERR"; return 2; } close OUT; close ERR; } 

then call setEnvironment(); once before the while loop, and call restoreEnvironment(); inside the while, but before the fork (incidentally, do not forget to also add $pid to @pids if your actual code does not do that already):

... $g_LOGFILE="parent.log"; setEnvironment(); while ($file = readdir(DIR)) { restoreEnvironment(); my $pid = fork; if ( $pid ) { push @pids, $pid;   ... 

Why and how does this work? We simply want to temporarily restore the original STDOUT before forking, so that the child's tee actually writes directly to the original STDOUT (e.g. your terminal) instead of writing through the parent's tee (which is what injected child lines into parent.log.) In answer to one of your questions, whoever wrote the code to set OUT and ERR must have had exactly the above in mind.

Here's what you now get at the end of the day:

$ rm -f parent.log child.log $ perl test.pl child parent child parent parent child parent child parent $ cat parent.log parent parent parent parent parent $ cat child.log child child child child child 
Source Link
vladr
  • 67k
  • 18
  • 131
  • 132
Loading