Tuesday, April 13, 2010

system() vs `backtick`

system() vs `backtick`

by dovert (Initiate)
| Log in | Create a new user | The Monastery Gates | Super Search |
| Seekers of Perl Wisdom | Meditations | PerlMonks Discussion |
| Obfuscation | Reviews | Cool Uses For Perl | Perl News | Q&A | Tutorials |
| Poetry | Recent Threads | Newest Nodes | Donate | What's New |

on Aug 06, 2004 at 19:02 UTC ( #380670=perlquestion: print w/ replies, xml ) Need Help??
dovert has asked for the wisdom of the Perl Monks concerning the following question:
update 2004/8/10: Red Hat has shown me (by invoking the perl in a 'kernel backward compatibility mode' that there is some (as yet unidentified) incompatibility between perl 5 and the new kernel, probably in the threading code. We're still trying to peel the onion. Thanks for your responses - a little feedback for the interested. The child process never gets to main() in the hang situation, (ie is not loooking for input) In fact, swapping 'ls' in as the called program doesn't change the behavior. I have a working perl program that, among other things, uses system() to run some other programs. I upgraded a Linux box from RH 9.3 to Enterprise Linux WS 3.1 and the program no longer works. (This is Perl 5.004_04) I can see that perl has forked, but the child is hanging, and the parent is waiting. ^C interrupts the child, and the parent completes. I discovered that if I run the program in `backticks`, it behaves properly. But I don't want to seek out all the system() calls & replace them & I'd like to know what is going on. So, I am interested in any insight about what is different enough about these two ways of running the program, that might make the difference. Or if you have heard of problems in this version of RH Linux. (It is not 'convenient' to upgrade the perl version, BTW) I'd be happy for any clues about where to look.
Comment on system() vs `backtick`
Re: system() vs `backtick`
by Prior Nacre V (Hermit) on Aug 06, 2004 at 19:21 UTC

    The difference is:

    system()
    runs command and returns command's exit status
    backticks
    runs command and returns the command's output

    Can't offer any help on O/S issue.

    Regards,

    PN5

Re: system() vs `backtick`
by dave_the_m (Vicar) on Aug 06, 2004 at 19:24 UTC
    Try strace -p pid on the child process to see what it's hanging on, and if it's on I/O, use lsof -p pid to see what file/socket etc it's hanging on.

    Dave.

Re: system() vs `backtick`
by hmerrill (Friar) on Aug 06, 2004 at 19:43 UTC
    I would suggest you file a bug in bugzilla on Red Hat's site against Enterprise Linux WS 3.1 for the "Perl" package, and copy and paste exactly the info you've written here. If you're lucky the "Perl" package owner at Red Hat may respond quickly. If you can get the email address of the owner of the "Perl" package at Red Hat, try sending him/her a message asking your question.
Re: system() vs `backtick`
by etcshadow (Priest) on Aug 06, 2004 at 20:36 UTC
    It depends on what the program is that you are running... but another possible issue is this: When running a command with system(), it is hooked up directly to your terminal, both for output and input... just as though a user had run that command at a shell prompt. When running a command with backticks, the input (as well as stderr) is still hooked up to the terminal, but the output stream is no longer the terminal... it is a pipe back to the parent (perl) process.

    Why does this matter? Well some programs will produce different output (or just generally work differently) if they detect that they are attached to a terminal than if they are not. For example, at least on many linux variants (can't speak for all *nixes), the ps command will format it's output for a terminal (it sets the the output width to the width of your terminal) if it sees that it is outputting to a terminal, and otherwise it will truncate its output width at 80 characters. Likewise, ls may use terminal escape code to set the color of file-names to indicate permissions or types. Also, ls may organize its output into a pretty looking table when writing to a terminal, but make a nice neat list when NOT writing to a terminal.

    Anyway, an easy way to check this out with your program is via a useless use of cat such as this:

    [me@host]$ command
    ...
    [me@host]$ command | cat
    ...

    And comparing the differences in the output. You can see the same thing (sorta) happening between system and backticks with this (which simply checks to see if the output stream is attached to a terminal or not):

    [me@host]$ perl -e 'print `perl -le "print -t STDOUT"`'

    [me@host]$ perl -e 'system q(perl -le "print -t STDOUT")'
    1
    [me@host]$

    As a shameless personal plug, I've actually written a node about how you can fool a process into thinking that it is connected to a terminal when it is not. This may not be of the utmost use to you in fixing your problem... but it is apropos.

    ------------
    :Wq
    Not an editor command: Wq
      As a shameless personal plug, I've actually written a node about how you can fool a process into thinking that it is connected to a terminal when it is not. This may not be of the utmost use to you in fixing your problem... but it is apropos.

      That is not needed here.

      The OP says that the command runs fine in backticks, but hungs when runs with system. The program probably waits for input (confirmation) when run on a terminal, that's why it hangs. What the OP actually needs is to fool the program it's not running interactively, by calling it through a backtick or redirecting its stdout. This is much simpler to acheive. It might even be unneccessary if the program has some command line switch to force it not to ask questions. Many programs like rm or fsck have such an option: if you give rm a file for which you do not have write access, it promts you whether you want to delete it, you can override this with the -f switch or by redirecting its stdin. Running rm in backticks redirects the stdout which is not enough for rm: it prompts for a confirmation, even if stderr is redirected too, and if you don't see the error it appears to hang.

Re: system() vs `backtick`
by sgifford (Prior) on Aug 06, 2004 at 22:00 UTC
    backticks send the executed program's STDOUT to a variable, and system sends it to your main program's STDOUT. So it could depend on what your main program's STDOUT is connected to. If it's connected to something that blocks, for example, or something that returns an error when you write to it, that could explain the problem.
Re: system() vs `backtick`
by hossman (Parson) on Aug 07, 2004 at 00:31 UTC

    Many people have have pointed out the difference between `` and system(), but I'd like to suggest that the problem you're seeing might not be something you need to fix in your perl script. The problem might be that in upgrading your RetHat distro, the program(s) you are executing using system() may have changed, such that if they detect they are running attached to a terminal, they wait for input on STDIN. (and in the old version, the program may not have assumed this).

    It's also important to remember that system() adn `` can/will pass your input to "/bin/sh -c" if it contains shell metacharacters, and on many newer systems /bin/sh is just a symlink to /bin/bash -- which may also be why you are now seeing a different in the behavior of your script. Your old distorbution may have genuinely had "sh" installed, which may have involved your program(s) differently so that they didn't know they were attached to a terminal.

      Regarding the compatibility of bash and sh... Bash is supposed to run in a compatibility when invoked as "sh" (by "compatibility mode" I mean that it should function in exactly the same way as sh). Of course, I cannot speak for how well it pulls this off. :-D
      ------------
      :Wq
      Not an editor command: Wq

1 comment:

Unknown said...

Hi Rajeev,

The Blog is very nice and userfull.

Regards,

Shariff.