4

Problem

When running exec in perl, I am am unable to redirect the output to a file.

I am running vlc in the exec but since i doubt everyone has it set up I have replaced with echo below, it shows same behaviour for the example.

I am only interested in exec 'command','args' format of exec not the one that spawns a shell since it spawns a subshell with vlc which still prints to screen + other problems with killing it cleanly.


Code

use strict;
use warnings;

my $pid = fork;
if (!defined $pid) {
    die "Cannot fork: $!";
}
elsif ($pid == 0) {
    exec "/usr/bin/echo","done";
}

Tried

exec "/usr/bin/echo","done",">/dev/null";

As expected just prints ">/dev/null", but was worth a try.

exec "/usr/bin/echo done >/dev/null";

Runs sh which then runs echo, works here, but not in my actual problem with vlc, thought i would include anyway since someone will surely suggest it.

Question

How do I redirect output from this exec when using 'command','args' to a file?

Extra

Any more info needed please ask.

11
  • try exec '/usr/bin/echo', 'done'; Commented Sep 27, 2017 at 8:51
  • are you just trying to send the output of the exectuted command to a file? Commented Sep 27, 2017 at 8:55
  • 3
    I think the >/dev/null is part of the shell. If you run exec '/usr/bin/echo', 'done' no shell is involved, which is the idea of the argument list. And without a shell, there is no way to redirect. You need to find a different way to change the handles that the program gets. But I don't know how unfortunately. Commented Sep 27, 2017 at 9:10
  • 1
    @simbabque Looks like changing STDOUT does work, just not with select strangely? Commented Sep 27, 2017 at 11:10
  • 1
    It makes sense actually. select does not change STDOUT. It changes the handle that Perl uses to write to by default. I didn't think of that. Well done. :) Commented Sep 27, 2017 at 11:12

2 Answers 2

4

Turns out you can just change the file descriptors before the exec

use strict;
use warnings;

my $pid = fork;
if (!defined $pid) {
    die "Cannot fork: $!";
}
elsif ($pid == 0) {
    open STDOUT, ">", '/logger/log' or die $!;
    open STDERR, ">", '/logger/log' or die $!;
    exec "/usr/bin/echo","done";
 }
Sign up to request clarification or add additional context in comments.

Comments

0

I suppose if you just need to print to file, this should work.

easiest possible way to capture the output is by using backticks.

use strict;
use warnings;

open (my $file, '>', 'output.log');
my $pid = fork;
if (!defined $pid) {
    die "Cannot fork: $!";
}
elsif ($pid == 0) {
    print $file `/usr/bin/echo done`;
}

2 Comments

Again, exec does not return. It's like a fork, it runs and forgets. Your print line in the first example will never be reached. In fact, your Perl throws a warning to tell you that. Run this code, and you'll see what I mean: perl -E 'END{say"end"} exec q{sleep 5 && echo "foo"}; say "bar";'
@simbabque My mistake. Fixed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.