FAQ
Hi everyone,

I *just* started getting into learning python.
I am currently working on a menu'ing system to keep non admin people from
goofing things up on some FreeBSD servers in a datacenter. I have very
little BG in coding. My menu system has a section for allowing the admins
to edit the various config files for different servers. For instance the
first python script which I am doing prompts the user for a hostname of
the server that apache is running on. It will save that hostname in the
variable host.

host = raw_input("Enter a hostname: ");

Then I want to pass the $host variable to ssh. So it does something like
this:

ssh -l root $host vi /usr/local/etc/apache.conf

Which will allow the tech to edit the web servers config file. But he
wont need to know ssh, or or anything else. My long winded question is
how do I get python to call an external application?

If someone could point me in the right direction I would really
appreciate it. Thanks for your time!

Chris

Search Discussions

  • S713221 at Jan 4, 2001 at 7:57 am

    My long winded question is
    how do I get python to call an external application?

    If someone could point me in the right direction I would really
    appreciate it. Thanks for your time!

    Chris
    import os
    os.system('echo "hello"')
    hello

    >>>

    Hope that helps.

    Joal Heagney/AncientHart
  • Donn Cave at Jan 5, 2001 at 6:49 am
    Quoth "Chris Watson" <scanner at jurai.net>:
    I *just* started getting into learning python.
    I am currently working on a menu'ing system to keep non admin people from
    goofing things up on some FreeBSD servers in a datacenter. I have very
    little BG in coding. My menu system has a section for allowing the admins
    to edit the various config files for different servers. For instance the
    first python script which I am doing prompts the user for a hostname of
    the server that apache is running on. It will save that hostname in the
    variable host.

    host = raw_input("Enter a hostname: ");

    Then I want to pass the $host variable to ssh. So it does something like
    this:

    ssh -l root $host vi /usr/local/etc/apache.conf

    Which will allow the tech to edit the web servers config file. But he
    wont need to know ssh, or or anything else. My long winded question is
    how do I get python to call an external application?

    If someone could point me in the right direction I would really
    appreciate it. Thanks for your time!
    The easiest thing to write is

    import os
    ...
    os.system('ssh -l root %s vi /usr/local/etc/apache.conf' % host)


    It's also about as dangerous as anything you can do in Python. It
    puts you completely at the mercy of whoever typed in that text at
    the "Enter a hostname: " prompt. Intentionally or not, a space
    or a semi-colon etc. could yield very different results than you
    intend.

    Luckily, with Python 2.0 we're getting to the point where you can
    do this in a safer way without writing all the fork & exec stuff
    yourself. The function, os.spawnv(), is apparently here for
    compatibility with Windows! but it seems to be what we need;
    you can look at the os module to see how it works if you want.

    import os
    os.spawnv(os.P_WAIT, '/usr/local/bin/ssh', ('ssh', '-l', 'root',
    host, 'vi', '/usr/local/etc/apache.conf'))

    That last argument is a tuple of the argument list to ssh, starting
    with argv[0]. In the system() function, we would eventually invoke
    the shell to parse the string into these arguments, and that's where
    the unexpected metacharacters wreak their havoc. By passing the
    arguments directly to the ssh process, we avoid that.

    Now, for this particular command, ssh, you might as well fold the
    'vi' and the file together, because ssh is going to do that for
    the remote shell to parse back out. So don't think you can get
    a sanitary calculated argument list through to the remote shell -
    that can't happen. Your example is OK, because the remote command
    is constant.

    Donn Cave, donn at oz.net
  • Chris Watson at Jan 5, 2001 at 7:47 am

    The easiest thing to write is

    import os
    ...
    os.system('ssh -l root %s vi /usr/local/etc/apache.conf' % host)


    It's also about as dangerous as anything you can do in Python. It
    puts you completely at the mercy of whoever typed in that text at
    the "Enter a hostname: " prompt. Intentionally or not, a space
    or a semi-colon etc. could yield very different results than you
    intend.
    Someone else pointed out the exact same way. However they also described
    it was bad h0h0 magic to do it that way. So...
    Luckily, with Python 2.0 we're getting to the point where you can
    do this in a safer way without writing all the fork & exec stuff
    yourself. The function, os.spawnv(), is apparently here for
    compatibility with Windows! but it seems to be what we need;
    you can look at the os module to see how it works if you want.

    import os
    os.spawnv(os.P_WAIT, '/usr/local/bin/ssh', ('ssh', '-l', 'root',
    host, 'vi', '/usr/local/etc/apache.conf'))

    That last argument is a tuple of the argument list to ssh, starting
    with argv[0]. In the system() function, we would eventually invoke
    the shell to parse the string into these arguments, and that's where
    the unexpected metacharacters wreak their havoc. By passing the
    arguments directly to the ssh process, we avoid that.
    I had thought about this briefly as well. And decided on an earlier
    repliers advice it would be wiser to copy the file to the local machine
    instead of editing it remotely.
    Now, for this particular command, ssh, you might as well fold the
    'vi' and the file together, because ssh is going to do that for
    the remote shell to parse back out. So don't think you can get
    a sanitary calculated argument list through to the remote shell -
    that can't happen. Your example is OK, because the remote command
    is constant.
    Well what I finally came up with, and I am no coder by any means, was the
    following:

    #!/usr/local/bin/python

    import os

    host = raw_input("Enter a hostname: ");

    # Copy the file from the remote server to the local machine.
    os.system("scp user@%s:/home/user/TESTFILE /tmp/TESTFILE" % host)

    # Edit the local copy.
    os.system("vi /tmp/TESTFILE")

    # "Push" the new config file from the local machine to the remote machine
    # using a secure ssh transport
    os.system("rsync -v -P -p -e ssh /tmp/TESTFILE user@%s:/home/user/TESTFILE" % host)


    How does this fare? Is this an acceptable solution? Or does this have
    the words "GLARING BONE HEAD" in neon letters stamped on it?
    I appreciate the replies and advice! Python seems to have a great group of
    people surrounding it. Have a good weekend everyone!!

    --
    =============================================================================
    -Chris Watson (316) 326-3862 | FreeBSD Consultant, FreeBSD Geek
    Work: scanner at jurai.net | Open Systems Inc., Wellington, Kansas
    Home: scanner at deceptively.shady.org | http://open-systems.net
    =============================================================================
    WINDOWS: "Where do you want to go today?"
    LINUX: "Where do you want to go tommorow?"
    BSD: "Are you guys coming or what?"
    =============================================================================
    irc.openprojects.net #FreeBSD -Join the revolution!
    ICQ: 20016186
  • Donn Cave at Jan 5, 2001 at 5:54 pm
    Quoth Chris Watson (Quoting myself)
    The easiest thing to write is

    import os
    ...
    os.system('ssh -l root %s vi /usr/local/etc/apache.conf' % host)


    It's also about as dangerous as anything you can do in Python. It
    puts you completely at the mercy of whoever typed in that text at
    the "Enter a hostname: " prompt. Intentionally or not, a space
    or a semi-colon etc. could yield very different results than you
    intend.
    Someone else pointed out the exact same way. However they also described
    it was bad h0h0 magic to do it that way. So...
    Luckily, with Python 2.0 we're getting to the point where you can
    do this in a safer way without writing all the fork & exec stuff
    yourself. The function, os.spawnv(), is apparently here for
    compatibility with Windows! but it seems to be what we need;
    you can look at the os module to see how it works if you want.

    import os
    os.spawnv(os.P_WAIT, '/usr/local/bin/ssh', ('ssh', '-l', 'root',
    host, 'vi', '/usr/local/etc/apache.conf'))

    That last argument is a tuple of the argument list to ssh, starting
    with argv[0]. In the system() function, we would eventually invoke
    the shell to parse the string into these arguments, and that's where
    the unexpected metacharacters wreak their havoc. By passing the
    arguments directly to the ssh process, we avoid that.
    I had thought about this briefly as well. And decided on an earlier
    repliers advice it would be wiser to copy the file to the local machine
    instead of editing it remotely.
    Now, for this particular command, ssh, you might as well fold the
    'vi' and the file together, because ssh is going to do that for
    the remote shell to parse back out. So don't think you can get
    a sanitary calculated argument list through to the remote shell -
    that can't happen. Your example is OK, because the remote command
    is constant.
    Well what I finally came up with, and I am no coder by any means, was the
    following:

    #!/usr/local/bin/python

    import os

    host = raw_input("Enter a hostname: ");

    # Copy the file from the remote server to the local machine.
    os.system("scp user@%s:/home/user/TESTFILE /tmp/TESTFILE" % host)

    # Edit the local copy.
    os.system("vi /tmp/TESTFILE")

    # "Push" the new config file from the local machine to the remote machine
    # using a secure ssh transport
    os.system("rsync -v -P -p -e ssh /tmp/TESTFILE user@%s:/home/user/TESTFILE" % host)
    So picture what happens if the input isn't legit.

    os.system("scp user@%s:/home/user/TESTFILE /tmp/TESTFILE" % "; rm -r /*; ")
    --> scp user@; rm -r /*; :/home/user/TESTFILE /tmp/TESTFILE

    Want to try that and see what happens? That's an intentionally hostile
    input (don't try it, really.) Accidental input errors might be harmless,
    or might not.

    I didn't see anything wrong with the ssh in your initial post, the
    problem was system(). system() + user-supplied input = unpredictable
    results. Use spawnv().

    Donn Cave, donn at u.washington.edu
  • Joel Ricker at Jan 5, 2001 at 11:19 pm
    Donn Cave wrote in message <9351o8$8qm$1 at nntp6.u.washington.edu>...
    try that and see what happens? That's an intentionally hostile
    input (don't try it, really.) Accidental input errors might be harmless,
    or might not.

    I didn't see anything wrong with the ssh in your initial post, the
    problem was system(). system() + user-supplied input = unpredictable
    results. Use spawnv().

    I'm not sure if you are familar with perl but perl has a pragma called Taint
    that when enabled prohibits the use of user supplied input until the proper
    input is regexed out of it - for example, usernames shouldn't have any
    punctuation other than _ or control codes, etc. I'm not sure exactly what
    Python has in this regard as this is Day 1 of my Perl Recovery Program (*s*)
    but its a mindset worth applying.

    Joel


    I'd
  • Donn Cave at Jan 6, 2001 at 12:33 am
    Quoth "Joel Ricker" <joejava at dragonat.net>:
    Donn Cave wrote in message <9351o8$8qm$1 at nntp6.u.washington.edu>...
    try that and see what happens? That's an intentionally hostile
    input (don't try it, really.) Accidental input errors might be harmless,
    or might not.

    I didn't see anything wrong with the ssh in your initial post, the
    problem was system(). system() + user-supplied input = unpredictable
    results. Use spawnv().

    I'm not sure if you are familar with perl but perl has a pragma called Taint
    that when enabled prohibits the use of user supplied input until the proper
    input is regexed out of it - for example, usernames shouldn't have any
    punctuation other than _ or control codes, etc. I'm not sure exactly what
    Python has in this regard as this is Day 1 of my Perl Recovery Program (*s*)
    but its a mindset worth applying.
    I'd like to see people try spawnv(). (Or spawnvp(), whatever.)

    It's nice to be able to clean up input for the shell command line, and
    maybe it's even reliable enough. As a mindset, I'm not sure. If you
    need to walk a high-wire, then a safety net is a good idea. If you
    actually could just cross at the street level, but everyone takes the
    high-wire because they don't like to walk up and down the stairs and
    there's a safety net, that puts the safety net in a different perspective.
    You can still break your neck.

    Until now, we could only say "system() is scary, but the alternatives
    are complex and laborious." Now 2.0 has a reasonably handy alternative.
    It's safer, it's faster, would appear to be portable. Say no to
    system(), at least with calculated inputs.

    Donn Cave, donn at u.washington.edu
  • Jim Dennis at Jan 7, 2001 at 1:22 pm

    In article <935p59$cga$1 at nntp6.u.washington.edu>, Donn Cave wrote:
    Quoth "Joel Ricker" <joejava at dragonat.net>:
    Donn Cave wrote in message <9351o8$8qm$1 at nntp6.u.washington.edu>...
    try that and see what happens? That's an intentionally hostile
    input (don't try it, really.) Accidental input errors might be harmless,
    or might not.
    I didn't see anything wrong with the ssh in your initial post, the
    problem was system(). system() + user-supplied input = unpredictable
    results. Use spawnv().
    I'm not sure if you are familar with perl but perl has a pragma called Taint
    that when enabled prohibits the use of user supplied input until the proper
    input is regexed out of it - for example, usernames shouldn't have any
    punctuation other than _ or control codes, etc. I'm not sure exactly what
    Python has in this regard as this is Day 1 of my Perl Recovery Program (*s*)
    but its a mindset worth applying.
    I'd like to see people try spawnv(). (Or spawnvp(), whatever.)
    It's nice to be able to clean up input for the shell command line, and
    maybe it's even reliable enough. As a mindset, I'm not sure. If you
    need to walk a high-wire, then a safety net is a good idea. If you
    actually could just cross at the street level, but everyone takes the
    high-wire because they don't like to walk up and down the stairs and
    there's a safety net, that puts the safety net in a different perspective.
    You can still break your neck.
    Until now, we could only say "system() is scary, but the alternatives
    are complex and laborious." Now 2.0 has a reasonably handy alternative.
    It's safer, it's faster, would appear to be portable. Say no to
    system(), at least with calculated inputs.
    Donn Cave, donn at u.washington.edu
    system() is scary because it spawns a shell, which parses
    the input as a command line *IN THE USERS ENVIRONMENT*. Thus
    there are various environement settings like PATH, possibly
    including aliases and shell functions that can also invisibly
    affect what is run.

    Note that Taint checking is not a panacea. In only enforces
    a policy that you perform some substition/regex filtering operation
    on your strings before you pass them to your system or eval functions.
    It doesn't "know" what constitutes a safe set of filtering parameters
    for each shell or whatever. Like a safety on a firearm it helps a good
    programmer avoid shooting himself in the foot but it doesn't unload
    the gun for you!

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedJan 4, '01 at 6:57a
activeJan 7, '01 at 1:22p
posts8
users7
websitepython.org

People

Translate

site design / logo © 2022 Grokbase