Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > record every backtick on STDOUT or some log file

Reply
Thread Tools

record every backtick on STDOUT or some log file

 
 
perlnewbie
Guest
Posts: n/a
 
      04-23-2012
Hi,

I got a Perl script from my colleague which I am going to run on my server.

This script is written to setup some folder structure and to create some users/group/permission/ownership. So, most part of the script uses backtick to call OS commands with some logic behind it. (my question is not about whether backtick is good or bad).

I want to make a minimum changes to the script so that every backtick with variable interpolation (example: `cd $v` should be recorded as 'cd /var/tmp', same as executed by OS) is recorded on STDOUT/STDERR or to some log file..

I don't want to go and add print statement just before every backticks.

What should be the good minimum change (either internal change or thru somewrapper) with or without any modules would help my scenario?

I am looking for a summary of chmod, chown, mkdir OS commands executed by this perl script.

Thanks.
 
Reply With Quote
 
 
 
 
J. Gleixner
Guest
Posts: n/a
 
      04-23-2012
On 04/23/12 12:42, perlnewbie wrote:
> Hi,
>
> I got a Perl script from my colleague which I am going to run on my server.
>
> This script is written to setup some folder structure and to create some users/group/permission/ownership. So, most part of the script uses backtick to call OS commands with some logic behind it. (my question is not about whether backtick is good or bad).
>


BTW: Backticks are generally not good, so rewrite it or have your
colleague rewrite it using the correct Perl functions: chdir,
chmod, etc..

> I want to make a minimum changes to the script so that every backtick with variable interpolation (example: `cd $v` should be recorded as 'cd /var/tmp', same as executed by OS) is recorded on STDOUT/STDERR or to some log file.
>
> I don't want to go and add print statement just before every backticks.


That's probably the easiest way to do what you want.

>
> What should be the good minimum change (either internal change or thru some wrapper) with or without any modules would help my scenario?


Could also change them into a sub call:

e.g.
`cd $v`;

run( "cd $v" );

sub run
{
my $cmd = shift;

print "Running: $cmd\n";
my $out = `$cmd`;
print "Output: $out\n";
}
 
Reply With Quote
 
 
 
 
Tim McDaniel
Guest
Posts: n/a
 
      04-23-2012
In article <4f959dee$0$75671$>,
J. Gleixner <glex_no-> wrote:
>BTW: Backticks are generally not good, so rewrite it or have your
>colleague rewrite it using the correct Perl functions: chdir,
>chmod, etc..


Opinions may differ. I think that one should use tools that are
well-suited for the work. Personally, if the shell can do it
perfectly well, I'm as inclined to use the shell as not, especially if
it's useful that it affect only itself and not the Perl program.
E.g., maybe I want a bit of script to "cd '$dir' && munge foo.cfg
out.ppp" but I want the Perl program to stay where it is.

But I may be atypical, because I know how to do bullet-resistant
shell coding. It *is* harder to do; much easier to have

mkdir($dir,0777) or crash("my_mkdir: mkdir '$dir' failed: $!");

or use autodie (I think it is).

>Could also change them into a sub call:


I recommend that. I usually call it my_system. I usually have it
echo the final command line, and have a global debug boolean that
makes it only do the output without running it, and analyze $? and $!
and such. Maybe I have a log. The advantage of a sub is that you can
do anything.

I see that once I did

use English;

# Borrowed from the perlipc man page.
sub kidopen($@) {
my ($dir, @cmd) = @_;
my $pid;
my $sleep_count = 0;
if ($dir eq '<') {
$dir = '-|';
} elsif ($dir eq '>') {
$dir = '|-';
} else {
die "$0: internal: kidopen() has invalid direction $dir, ";
}
if ($dir eq '|-') {
open(KID, '|less');
return;
}
for (; {
$pid = open(KID, $dir);
last if defined $pid;
warn "$0: Cannot fork a child: $!\n";
die "$0: Too many attempts failed. Dying.\n"
if $sleep_count++ > 6;
sleep 10;
}

if ($pid) { # parent
# Return to caller to do something interesting.
} else { # child
exec @cmd or
die("$0: Cannot exec program: $!.\n",
" Program: @cmd");
# NOTREACHED
}
}

sub kidclose() {
$ERRNO = 0;
# print STDERR "=== DEBUG in kidclose\n";
close(KID) or
warn("$0: Child exited with code $CHILD_ERROR, ",
"errno ", 0+$ERRNO, ": $ERRNO.\n");
# print STDERR "=== DEBUG done in kidclose\n";
}

The advantage is that "exec @cmd" means that it will NOT be subject to
the vagarities of shell parsing, which is great if you have one
program with possible unusual arguments that you want not to be
violated by the shell, but really lousy if you want
cd $dir && cp * /scratch/wav

--
Tim McDaniel,
 
Reply With Quote
 
Rainer Weikusat
Guest
Posts: n/a
 
      04-23-2012
(Tim McDaniel) writes:
> In article <4f959dee$0$75671$>,
> J. Gleixner <glex_no-> wrote:
>>BTW: Backticks are generally not good, so rewrite it or have your
>>colleague rewrite it using the correct Perl functions: chdir,
>>chmod, etc..

>
> Opinions may differ. I think that one should use tools that are
> well-suited for the work. Personally, if the shell can do it
> perfectly well, I'm as inclined to use the shell as not, especially if
> it's useful that it affect only itself and not the Perl program.
> E.g., maybe I want a bit of script to "cd '$dir' && munge foo.cfg
> out.ppp" but I want the Perl program to stay where it is.


Perl supports fork. Also, when using the Perl functions, it is
possible to implement real error handling because the actual system
error codes are available.
 
Reply With Quote
 
Tim McDaniel
Guest
Posts: n/a
 
      04-23-2012
In article < >,
Rainer Weikusat <> wrote:
> (Tim McDaniel) writes:
>> In article <4f959dee$0$75671$>,
>> J. Gleixner <glex_no-> wrote:
>>>BTW: Backticks are generally not good, so rewrite it or have your
>>>colleague rewrite it using the correct Perl functions: chdir,
>>>chmod, etc..

>>
>> Opinions may differ. I think that one should use tools that are
>> well-suited for the work. Personally, if the shell can do it
>> perfectly well, I'm as inclined to use the shell as not, especially if
>> it's useful that it affect only itself and not the Perl program.
>> E.g., maybe I want a bit of script to "cd '$dir' && munge foo.cfg
>> out.ppp" but I want the Perl program to stay where it is.

>
>Perl supports fork.


Quite so, but doing so reliably and well takes some effort, as shown
by "man perlipc".

>Also, when using the Perl functions, it is possible to implement real
>error handling because the actual system error codes are available.


Except that programs generally do their own error checking on their
own pretty well, like for "mv afile /unwritable", but you have to
implement that in Perl on your own, so that's actually an argument
*against* doing it in Perl.

Except, as I noted, if you're trying to do sophisticated quoting or
control in shell. It takes some knowledge and effort to do
bullet-resistant programming in either shell or Perl, and
unfortunately the skills needed for one often don't translate to the
other.

--
Tim McDaniel,
 
Reply With Quote
 
Rainer Weikusat
Guest
Posts: n/a
 
      04-23-2012
(Tim McDaniel) writes:
> Rainer Weikusat <> wrote:
>> (Tim McDaniel) writes:


[...]

>>> if the shell can do it perfectly well, I'm as inclined to use the
>>> shell as not, especially if it's useful that it affect only itself
>>> and not the Perl program. E.g., maybe I want a bit of script to
>>> "cd '$dir' && munge foo.cfg out.ppp" but I want the Perl program
>>> to stay where it is.

>>
>>Perl supports fork.

>
> Quite so, but doing so reliably and well takes some effort, as shown
> by "man perlipc".


perlipc essentially only mentions fork as part of a daemonization
procedure. But that's not what you get with backticks. These just
instruct perl to fork, exec the shell and pass the command in
backticks as argument to it in a suitable way (which then causes the
shell to fork and exec the actual command, with the shell waiting for
the command and perl waiting for the shell. And any 'result' is only
available as text which needs to be interpreted/ parsed to get at the
actual data). And you can as well just fork the perl process and
execute the system calls changing the process state directly without
affecting the state of the parent process.

>>Also, when using the Perl functions, it is possible to implement real
>>error handling because the actual system error codes are available.

>
> Except that programs generally do their own error checking on their
> own pretty well, like for "mv afile /unwritable", but you have to
> implement that in Perl on your own, so that's actually an argument
> *against* doing it in Perl.


Minus output, the only result information perl gets from an external
command is generally "it worked" or "it failed" no matter what that
external command might have done. And this essentially makes it
impossible to implement an _error handling strategies_ in Perl.
 
Reply With Quote
 
Tim McDaniel
Guest
Posts: n/a
 
      04-23-2012
In article < >,
Rainer Weikusat <> wrote:
> (Tim McDaniel) writes:
>> Rainer Weikusat <> wrote:
>>>Perl supports fork.

>>
>> Quite so, but doing so reliably and well takes some effort, as shown
>> by "man perlipc".

>
>perlipc essentially only mentions fork as part of a daemonization
>procedure.


perlipc in 5.8.8 mentions safe implementations of pipe open (which has
a fork implicitly behind the scenes) and backtick, defining "safe" as
"you can do it without the shell getting its grubby fingerprints on
the arguments".

To be fair, though, my Perl scripts don't usually have a problem with
chdir and such, so that aspect of using shell commands is not often of
use.

>>>Also, when using the Perl functions, it is possible to implement real
>>>error handling because the actual system error codes are available.

>>
>> Except that programs generally do their own error checking on their
>> own pretty well, like for "mv afile /unwritable", but you have to
>> implement that in Perl on your own, so that's actually an argument
>> *against* doing it in Perl.

>
>Minus output, the only result information perl gets from an external
>command is generally "it worked" or "it failed" no matter what that
>external command might have done. And this essentially makes it
>impossible to implement an _error handling strategies_ in Perl.


In practice, "it worked || it failed" has been good enough for me so
far. The shell programs I've called have been good enough about
reporting their errors for me to realize the underlying problem, and I
can't think of anything different to do depending on which failure
happened.

I'm not saying you're wrong, mind you. If you want to do a mkdir and
need to do different things based on which error happened, or you need
efficiency, then you have to call Perl's mkdir and look at the error
status. It's just that, for me, I haven't needed either, and
therefore things like
system('mkdir', '-p', $tmpdir) or die "cannot create '$tmpdir'.\n";
work for my purposes.

And I certainly don't want to re-implement
system('rm', '-rf', $dir) or die ...
in Perl.

--
Tim McDaniel,
 
Reply With Quote
 
Rainer Weikusat
Guest
Posts: n/a
 
      04-24-2012
(Tim McDaniel) writes:
> In article < >,
> Rainer Weikusat <> wrote:
>> (Tim McDaniel) writes:
>>> Rainer Weikusat <> wrote:
>>>>Perl supports fork.
>>>
>>> Quite so, but doing so reliably and well takes some effort, as shown
>>> by "man perlipc".

>>
>>perlipc essentially only mentions fork as part of a daemonization
>>procedure.

>
> perlipc in 5.8.8 mentions safe implementations of pipe open (which has
> a fork implicitly behind the scenes) and backtick, defining "safe" as
> "you can do it without the shell getting its grubby fingerprints on
> the arguments".


That's obviously not relevant in the context of 'executing system
calls which change the state of a process without affecting the state
of "the process which caused that"'. Invoking the safely shell with
input data from untrusted sources "takes some effort" but that's
besides the point.

[...]

> And I certainly don't want to re-implement
> system('rm', '-rf', $dir) or die ...
> in Perl.


That's not particularly difficult and I've probably done so a couple
of times: If I can get by writing a shell scripts, I'll write a shell
script.

 
Reply With Quote
 
Chris Davies
Guest
Posts: n/a
 
      04-25-2012
perlnewbie <> wrote:
> example: `cd $v` should be recorded as 'cd /var/tmp', same as executed
> by OS


You are aware that `cd $v` (for any value of $v) is a meaningless
operation on a UNIX/Linux type system?

Chris

 
Reply With Quote
 
 
 
Reply

Thread Tools

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 On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Separate output for log file and stdout amit.uttam@gmail.com Python 4 05-21-2008 10:59 PM
beginner Q: Kernel#puts, STDOUT, $stdout relation Andreas S Ruby 3 12-09-2006 12:39 AM
Problems redirecting STDOUT (NOT sys.stdout) to a pipe. Elad Python 0 03-19-2006 01:30 PM
copy stdout fails with permission denied when stdout is redirected brian.mabry.edwards@gmail.com Perl Misc 2 12-07-2005 10:49 PM
Writing to stdout and a log file Mike Python 7 04-20-2005 11:27 PM



Advertisments