mscharrer has asked for the wisdom of the Perl Monks concerning the following question:

Dear fellow monks,
I'm calling a unix command from my Perl script and like to avoid any text going the STDERR or STDOUT coming from the command. So I just added a &>/dev/null to the system string like I know it from the BASH shell prompt.
To my surprise this doesn't work, I still get the STDERR on the calling shell:

system("dd if=/dev/zero of=$SIZE bs=1M count=0 seek=$SIZEMB &>/dev/nul +l})'; # prints to STDERR: 10+0 records in 10+0 records out 10485760 bytes (10 MB) copied, 0.00426433 s, 2.5 GB/s

If I now change the "&>" - which affects STDOUT and STDERR - to "2>" - which only affects STDERR - it works:

system("dd if=/dev/zero of=$SIZE bs=1M count=0 seek=$SIZEMB &>/dev/nul +l})'; # prints nothing

Why is this? It's not a problem but I like to know it anyway. The redirect is handled by the shell (==calling shell (BASH)?) not by perl, isn't it? Please enlighten me.

PS: The dd command is used to create a sparse file. Does someone know how to create sparse files with Perl without using a system command?

Replies are listed 'Best First'.
Re: system and &>/dev/null
by Fletch (Bishop) on Oct 09, 2008 at 21:38 UTC

    Sounds like perl either isn't using bash or is using bash but calling it in such a manner that it's acting like vanilla sh (see the bash man page for how it changes its behavior based on the name it's called). The output from perl -V:sh may be illuminating.

    Update: And as for creating sparse files, just open the a file for writing, seek to the desired size, and truncate.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: system and &>/dev/null
by repellent (Priest) on Oct 09, 2008 at 22:23 UTC
    The Bourne shell sh may not recognize "&>". Try using "> /dev/null 2>&1" instead.
Re: system and &>/dev/null
by Bloodnok (Vicar) on Oct 10, 2008 at 18:13 UTC
    Aside from the previous suggestions regarding opening file internal to perl, AFAIC, you had the original re-direction wrong - it should've been >&, instead of the &> - that would run the dd(1) command in the background, totally ignoring the & ... which is why the 2>/dev/null, worked for you (twas the right way round).

    If you want to ignore all output i.e. STDOUT _&_ STDERR, then use >/dev/null 2>&1

    A user level that continues to overstate my experience :-))
Re: system and &>/dev/null
by broomduster (Priest) on Oct 09, 2008 at 23:24 UTC
    Does someone know how to create sparse files with Perl without using a system command?
    How about this:
    open my $fh, '>', 'zeros' or die "error opening fh: ($!)"; binmode $fh; print $fh pack "x512"; #512 bytes-- season to taste, loop as needed

      Doesn't seem to create a sparse file:

      [tmp]$ cat broomduster.pl open my $fh, '>', 'zeros' or die "error opening fh: ($!)"; binmode $fh; print $fh pack "x".(1024*1024*10); [tmp]$ rm zeros; perl broomduster.pl; ls -lh zeros; du -h zeros -rw-rw-r-- 1 duelafn 10M 2008-10-09 22:17 zeros 11M zeros

      However, the following works:

      [tmp]$ cat duelafn.pl open my $fh, '>', 'zeros' or die "error opening fh: ($!)"; seek $fh, 1024*1024*10 - 1, 0; print $fh "\0"; [tmp]$ rm zeros; perl duelafn.pl; ls -lh zeros; du -h zeros -rw-rw-r-- 1 duelafn 10M 2008-10-09 22:17 zeros 12K zeros

      Good Day,
          Dean

        This would not create a 100% sparse file because the last block would be all zero (even you print only one zero). Fletch was right in his above post, the combination of seek and truncate must be used.

        Here my first attempt from yesterday evening to create a halfway secure sub function which doesn't mess-up existing files:

        sub create_sparse { my ($file, $size) = @_; return if -e $file && ! -f _; return -2 if -e _ && -s _ >= $size; open my $fh, '+>', $file or return; eval { seek $fh, $size, 0 or die; truncate $fh, $size or die; } or do { close $fh; return; }; close $fh or return; return -1; }