outputting a command to the terminal?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Salerno

    outputting a command to the terminal?

    Here's my new project: I want to write a little script that I can type
    at the terminal like this:

    $ scriptname package1 [package2, ...]

    where scriptname is my module name and any subsequent arguments are the
    names of Linux packages to install. Running the script as above will
    create this line:

    sudo aptitude install package1 package2 ...

    It will run that line at the terminal so the package(s) will be installed.

    Now, the extra functionality I want to add (otherwise I would just
    install them normally!) is to save the package names to a text file so I
    can now the names of programs I've manually installed, if I ever want to
    check the list or remove packages.

    So creating the proper bash command (sudo aptitude install ...) is easy,
    and writing the names to a file is easy. But I have two questions:

    1. First of all, does Linux keep track of the packages you manually
    install? If so, then I won't have to do this at all.

    2. Assuming I write this, how do output the bash command to the
    terminal? Is there a particular module that Python uses to interact with
    the terminal window that I can use to send the install command to the
    terminal?

    Thanks.
  • Diez B. Roggisch

    #2
    Re: outputting a command to the terminal?

    John Salerno schrieb:
    Here's my new project: I want to write a little script that I can type
    at the terminal like this:
    >
    $ scriptname package1 [package2, ...]
    >
    where scriptname is my module name and any subsequent arguments are the
    names of Linux packages to install. Running the script as above will
    create this line:
    >
    sudo aptitude install package1 package2 ...
    >
    It will run that line at the terminal so the package(s) will be installed.
    >
    Now, the extra functionality I want to add (otherwise I would just
    install them normally!) is to save the package names to a text file so I
    can now the names of programs I've manually installed, if I ever want to
    check the list or remove packages.
    >
    So creating the proper bash command (sudo aptitude install ...) is easy,
    and writing the names to a file is easy. But I have two questions:
    >
    1. First of all, does Linux keep track of the packages you manually
    install? If so, then I won't have to do this at all.
    >
    2. Assuming I write this, how do output the bash command to the
    terminal? Is there a particular module that Python uses to interact with
    the terminal window that I can use to send the install command to the
    terminal?

    You don't put a command to the terminal. The shell executes commands.
    But it is mainly just a program itself - it can spawn subprocesses and
    make these execute the actual commands. so - the module you need is most
    probably subprocess.

    Diez

    Comment

    • Yu-Xi Lim

      #3
      Re: outputting a command to the terminal?

      John Salerno wrote:
      1. First of all, does Linux keep track of the packages you manually
      install? If so, then I won't have to do this at all.
      I assume you're using a Debian-based distro with aptitude as the front
      end. In which case, all dpkg operations should be logged in
      /var/log/dpkg.log

      Generally, after the initial installation, all subsequent operations are
      either updates of existing packages or packages you installed manually.
      Only rarely do you get new packages installed automatically as a result
      of an additional dependency from an original automatically installed
      package.

      If you know when you completed your initial installation, you can easily
      parse the log files to determine what else was installed after that.
      2. Assuming I write this, how do output the bash command to the
      terminal? Is there a particular module that Python uses to interact with
      the terminal window that I can use to send the install command to the
      terminal?
      I'm wondering about the need to "output the bash command to the
      terminal". It would probably suffice if your Python script just spawned
      an instance of the shell with the necessary command line. Take a look at
      the subprocess module.

      But this really calls for a bash script:

      #!/bin/bash
      echo $@ >/path/to/manual_install. log
      sudo aptitude install $@


      Shorter than the equivalent Python code. You could probably declare this
      as a function in your bash initialization files too, if you know how to
      do this.

      Comment

      • John Salerno

        #4
        Re: outputting a command to the terminal?

        Yu-Xi Lim wrote:
        I assume you're using a Debian-based distro with aptitude as the front
        end. In which case, all dpkg operations should be logged in
        /var/log/dpkg.log
        Yes, I'm using Ubuntu. But I checked this log file and I'm a bit
        confused. It has a lot of listings for 5-31-06, but I didn't even
        install Linux until last Saturday. The next date after 5-31 is 8-5-06,
        and I know I installed things between last Saturday and Aug. 5.

        (But this is OT, so don't worry about it.)
        I'm wondering about the need to "output the bash command to the
        terminal". It would probably suffice if your Python script just spawned
        an instance of the shell with the necessary command line. Take a look at
        the subprocess module.
        >
        But this really calls for a bash script:
        >
        #!/bin/bash
        echo $@ >/path/to/manual_install. log
        sudo aptitude install $@
        >
        >
        Shorter than the equivalent Python code. You could probably declare this
        as a function in your bash initialization files too, if you know how to
        do this.
        Hmm, interesting. I figured I could do this with a bash script, but I
        don't know bash at all and I'm trying to stick with Python. I don't
        quite understand your bash script (not familiar with the $@ syntax).

        I think I'll take a look at the subprocess module, just for fun. :)

        Comment

        • John Machin

          #5
          Re: outputting a command to the terminal?


          John Salerno wrote:
          >
          I think I'll take a look at the subprocess module, just for fun. :)
          .... and for learning too :-)

          Also, consider that some operating system commands are built into the
          shell (i.e. not run as a separate process), which makes using the
          subprocess module a bit difficult -- for more fun and learning, check
          out os.system()

          Cheers,
          John

          Comment

          • John Salerno

            #6
            Re: outputting a command to the terminal?

            Dennis Lee Bieber wrote:
            On Sun, 13 Aug 2006 20:21:26 -0400, John Salerno
            <johnjsal@NOSPA Mgmail.comdecla imed the following in comp.lang.pytho n:
            >
            >Yes, I'm using Ubuntu. But I checked this log file and I'm a bit
            >confused. It has a lot of listings for 5-31-06, but I didn't even
            >install Linux until last Saturday. The next date after 5-31 is 8-5-06,
            >and I know I installed things between last Saturday and Aug. 5.
            >>
            Pardon, between when?
            Wow, I can't believe how time goes. Aug. 5 *was* the first day! I knew I
            had installed it a week ago, but I was thinking it was the last Saturday
            in July, not Aug. 5 already!
            >
            August 5 was "last Saturday" if you ignore "yesterday" (well, since
            my watch says it is now Monday... "day before last").
            >
            I'd guess the "May 31" entries are those that were "snapshots" of
            the OS installer date. August 5, first Saturday in the month, might be
            the first non-standard installed package.
            >
            >Hmm, interesting. I figured I could do this with a bash script, but I
            >don't know bash at all and I'm trying to stick with Python. I don't
            >quite understand your bash script (not familiar with the $@ syntax).
            >>
            Well, I don't do shell scripts either, but... looking at the
            sample... "$@" is likely the shell equivalent of Python's sys.argv -- or
            *sys.argv if passed down

            Comment

            • Steven Bethard

              #7
              Re: outputting a command to the terminal?

              John Salerno wrote:
              Here's my new project: I want to write a little script that I can type
              at the terminal like this:
              >
              $ scriptname package1 [package2, ...]
              >
              where scriptname is my module name and any subsequent arguments are the
              names of Linux packages to install. Running the script as above will
              create this line:
              >
              sudo aptitude install package1 package2 ...
              >
              It will run that line at the terminal so the package(s) will be installed.
              >
              Now, the extra functionality I want to add (otherwise I would just
              install them normally!) is to save the package names to a text file so I
              can now the names of programs I've manually installed, if I ever want to
              check the list or remove packages.
              >
              So creating the proper bash command (sudo aptitude install ...) is easy,
              and writing the names to a file is easy. But I have two questions:
              >
              1. First of all, does Linux keep track of the packages you manually
              install? If so, then I won't have to do this at all.
              >
              2. Assuming I write this, how do output the bash command to the
              terminal? Is there a particular module that Python uses to interact with
              the terminal window that I can use to send the install command to the
              terminal?

              I don't know the answer to the first bit here, but I think the following
              should get you most of what you want as far as the second bit is concerned:


              ---------------------------- scriptname.py ----------------------------
              import argparse # http://argparse.python-hosting.com/
              import subprocess
              import sys

              def outputfile(file name):
              return open(filename, 'w')

              if __name__ == '__main__':
              # parse the command line arguments
              parser = argparse.Argume ntParser()
              parser.add_argu ment('packages' , metavar='packag e', nargs='+',
              help='one of the packages to install')
              parser.add_argu ment('--save', type=outputfile , default=sys.std out,
              help='a file to save the package names to')
              namespace = parser.parse_ar gs()

              # call the command
              command = ['sudo', 'aptitude', 'install'] + namespace.packa ges
              subprocess.call (command)

              # write the package name file
              for package_name in namespace.packa ges:
              namespace.save. write('%s\n' % package_name)
              -----------------------------------------------------------------------


              $ scriptname.py -h
              usage: scriptname.py [-h] [--save SAVE] package [package ...]

              positional arguments:
              package one of the packages to install

              optional arguments:
              -h, --help show this help message and exit
              --save SAVE a file to save the package names to



              STeVe

              Comment

              • John Salerno

                #8
                Re: outputting a command to the terminal?

                Steven Bethard wrote:
                John Salerno wrote:
                >Here's my new project: I want to write a little script that I can type
                >at the terminal like this:
                >>
                >$ scriptname package1 [package2, ...]
                >>
                >where scriptname is my module name and any subsequent arguments are
                >the names of Linux packages to install. Running the script as above
                >will create this line:
                >>
                >sudo aptitude install package1 package2 ...
                >>
                >It will run that line at the terminal so the package(s) will be
                >installed.
                >>
                >Now, the extra functionality I want to add (otherwise I would just
                >install them normally!) is to save the package names to a text file so
                >I can now the names of programs I've manually installed, if I ever
                >want to check the list or remove packages.
                >>
                >So creating the proper bash command (sudo aptitude install ...) is
                >easy, and writing the names to a file is easy. But I have two questions:
                >>
                >1. First of all, does Linux keep track of the packages you manually
                >install? If so, then I won't have to do this at all.
                >>
                >2. Assuming I write this, how do output the bash command to the
                >terminal? Is there a particular module that Python uses to interact
                >with the terminal window that I can use to send the install command to
                >the terminal?
                >
                >
                I don't know the answer to the first bit here, but I think the following
                should get you most of what you want as far as the second bit is concerned:
                >
                >
                ---------------------------- scriptname.py ----------------------------
                import argparse # http://argparse.python-hosting.com/
                import subprocess
                import sys
                >
                def outputfile(file name):
                return open(filename, 'w')
                >
                if __name__ == '__main__':
                # parse the command line arguments
                parser = argparse.Argume ntParser()
                parser.add_argu ment('packages' , metavar='packag e', nargs='+',
                help='one of the packages to install')
                parser.add_argu ment('--save', type=outputfile , default=sys.std out,
                help='a file to save the package names to')
                namespace = parser.parse_ar gs()
                >
                # call the command
                command = ['sudo', 'aptitude', 'install'] + namespace.packa ges
                subprocess.call (command)
                >
                # write the package name file
                for package_name in namespace.packa ges:
                namespace.save. write('%s\n' % package_name)
                -----------------------------------------------------------------------
                >
                >
                $ scriptname.py -h
                usage: scriptname.py [-h] [--save SAVE] package [package ...]
                >
                positional arguments:
                package one of the packages to install
                >
                optional arguments:
                -h, --help show this help message and exit
                --save SAVE a file to save the package names to
                >
                >
                >
                STeVe
                yikes! I'll have to take some time to study this! I appreciate it. :)

                Comment

                • Yu-Xi Lim

                  #9
                  Re: outputting a command to the terminal?

                  Dennis Lee Bieber wrote:
                  Well, I don't do shell scripts either, but... looking at the
                  sample... "$@" is likely the shell equivalent of Python's sys.argv -- or
                  *sys.argv if passed down
                  Yeah, kinda equivalent to *sys.argv[1:].

                  Comment

                  • Yu-Xi Lim

                    #10
                    Re: outputting a command to the terminal?

                    Steven Bethard wrote:
                    import argparse # http://argparse.python-hosting.com/
                    import subprocess
                    import sys
                    Why not the standard lib's optparse?

                    Comment

                    • Steven Bethard

                      #11
                      Re: outputting a command to the terminal?

                      John Salerno wrote:
                      Steven Bethard wrote:
                      >---------------------------- scriptname.py ----------------------------
                      >import argparse # http://argparse.python-hosting.com/
                      >import subprocess
                      >import sys
                      >>
                      >def outputfile(file name):
                      > return open(filename, 'w')
                      >>
                      >if __name__ == '__main__':
                      > # parse the command line arguments
                      > parser = argparse.Argume ntParser()
                      > parser.add_argu ment('packages' , metavar='packag e', nargs='+',
                      > help='one of the packages to install')
                      > parser.add_argu ment('--save', type=outputfile , default=sys.std out,
                      > help='a file to save the package names to')
                      > namespace = parser.parse_ar gs()
                      >>
                      > # call the command
                      > command = ['sudo', 'aptitude', 'install'] + namespace.packa ges
                      > subprocess.call (command)
                      >>
                      > # write the package name file
                      > for package_name in namespace.packa ges:
                      > namespace.save. write('%s\n' % package_name)
                      >-----------------------------------------------------------------------
                      >>
                      >>
                      >$ scriptname.py -h
                      >usage: scriptname.py [-h] [--save SAVE] package [package ...]
                      >>
                      >positional arguments:
                      > package one of the packages to install
                      >>
                      >optional arguments:
                      > -h, --help show this help message and exit
                      > --save SAVE a file to save the package names to
                      >
                      >
                      yikes! I'll have to take some time to study this! I appreciate it. :)

                      For just calling the command, the important lines are::

                      command = ['sudo', 'aptitude', 'install'] + namespace.packa ges
                      subprocess.call (command)

                      where you could have probably used ``sys.argv[1:]`` instead of
                      namespace.packa ges.


                      For writing the file, as I'm sure you've already figured out, the
                      important lines are::

                      for package_name in namespace.packa ges:
                      namespace.save. write('%s\n' % package_name)

                      where again, if you weren't using argparse, you could have used
                      ``sys.argv`` to determine the package names (namespace.pack ages) and the
                      file to write to (namespace.save ).


                      The remaining lines involving the ``parser`` object are basically
                      defining a command line interface in a similar way to what optparse in
                      the stdlib does. Sure, you could do all of this by fiddling with
                      sys.argv, but the argparse module will do all the parsing and
                      conversions for you, and give your script a meaningful usage message.
                      And I'm a firm believer in meaningful usage messages. =)

                      STeVe

                      P.S. Thank *you* for posting this. As a result, I've been convinced
                      that argparse should grow a 'outfile' type, something I've been debating
                      with myself about for a while now.

                      Comment

                      • John Salerno

                        #12
                        Re: outputting a command to the terminal?

                        Steven Bethard wrote:
                        P.S. Thank *you* for posting this. As a result, I've been convinced
                        that argparse should grow a 'outfile' type, something I've been debating
                        with myself about for a while now.
                        Heh heh. I'm glad my ignorance can inspire those around me. ;)

                        Comment

                        • Steven Bethard

                          #13
                          Re: outputting a command to the terminal?

                          Yu-Xi Lim wrote:
                          Steven Bethard wrote:
                          >import argparse # http://argparse.python-hosting.com/
                          >import subprocess
                          >import sys
                          >
                          Why not the standard lib's optparse?
                          The page referenced above gives a variety of reasons, but the two most
                          important things in this example are: argparse supports parsing of both
                          positional and optional arguments, and argparse generates better usage
                          messages.

                          Since argparse supports positional arguments, I can write something like::

                          parser.add_argu ment('packages' , ..., nargs='+', ...)

                          and then the arparse module will enforce that at least one positional
                          argument was given. With optparse, you'd do something like:

                          options, args = parser.parse_ar gs()
                          if not args:
                          parser.error('w rong number of arguments')

                          Basically, with optparse, anything that involves positional arguments
                          has to be handled by the user.

                          It's also worth pointing out the better usage messages. Notice that the
                          output looked like::

                          $ scriptname.py -h
                          usage: scriptname.py [-h] [--save SAVE] package [package ...]

                          positional arguments:
                          package one of the packages to install

                          optional arguments:
                          -h, --help show this help message and exit
                          --save SAVE a file to save the package names to

                          With the optparse, you'd get something like::

                          $ scriptname.py -h
                          usage: scriptname.py [OPTIONS]

                          options:
                          -h, --help show this help message and exit
                          --save SAVE a file to save the package names to

                          The argparse module knows how to create a meaningful usage message
                          instead of just "%prog [OPTIONS]", and the argparse module knows about
                          positional arguments, so you can have help messages for them too.

                          Ok, enough propaganda for now. ;-)

                          STeVe

                          Comment

                          • Simon Forman

                            #14
                            Re: outputting a command to the terminal?

                            John Salerno wrote:
                            Yu-Xi Lim wrote:
                            >
                            I assume you're using a Debian-based distro with aptitude as the front
                            end. In which case, all dpkg operations should be logged in
                            /var/log/dpkg.log
                            >
                            Yes, I'm using Ubuntu. But I checked this log file and I'm a bit
                            confused. It has a lot of listings for 5-31-06, but I didn't even
                            install Linux until last Saturday. The next date after 5-31 is 8-5-06,
                            and I know I installed things between last Saturday and Aug. 5.
                            >
                            (But this is OT, so don't worry about it.)
                            >
                            I'm wondering about the need to "output the bash command to the
                            terminal". It would probably suffice if your Python script just spawned
                            an instance of the shell with the necessary command line. Take a look at
                            the subprocess module.

                            But this really calls for a bash script:

                            #!/bin/bash
                            echo $@ >/path/to/manual_install. log
                            sudo aptitude install $@


                            Shorter than the equivalent Python code. You could probably declare this
                            as a function in your bash initialization files too, if you know how to
                            do this.
                            >
                            Hmm, interesting. I figured I could do this with a bash script, but I
                            don't know bash at all and I'm trying to stick with Python. I don't
                            quite understand your bash script (not familiar with the $@ syntax).
                            >
                            I think I'll take a look at the subprocess module, just for fun. :)
                            Hey John, Yu-Xi Lim's right. This is one of those (thankfully few)
                            cases where bash makes more sense to use than python (at least IMHO.)

                            To figure out about that $@, fire up your teminal and type "man bash"
                            ("!man bash" in IPython) (BTW, apropos of nothing, "man bash" is one of
                            my all time favorite commands ever. I always think of some comic-book
                            hero/monster shouting it, "MAN BASH!!" lol. Anyway...)

                            So, now you're looking at the man page for bash. It's very very long
                            and ubergeeky. Deep and amazing mysteries are contained (and kind of
                            explained) within it. You want information on $@ so we'll use the
                            search incantation to find and reveal it.

                            Type "/\$@" without the quotes, then press return. (What this
                            means/does: "/" is the manpage search command, it uses a regular
                            expression syntax not dissimilar to python's own. "\" escapes the next
                            character ("$", in this case) and we need to do that because "$" is
                            regular expression syntax for "end of line". The "$@" will now match,
                            um, "$@" correctly.)

                            Once you press return, man will scroll to put the first occurance of
                            "$@" at the top of your terminal and highlight it. On my system it's
                            this line (I narrowed my terminal so that quoted portions wouldn't wrap
                            badly in this posting):

                            "$@" as explained below under Special Parameters.

                            So far so good, '"$@" as explained below' looks promising. Rather than
                            scrolling down to find this "Special Parameters" section, let's keep
                            using the search.

                            Press "n" to scroll to the next occurance of our pattern "$@". On my
                            system this brings me to:

                            separate word. That is, "$@" is equivalent to
                            "$1" "$2" ... If the double-quoted expansion

                            Ah ha! Scrolling up a few lines, we see:

                            @ Expands to the positional parameters, starting
                            from one. When the expansion occurs within
                            double quotes, each parameter expands to a
                            separate word. That is, "$@" is equivalent to
                            "$1" "$2" ... If the double-quoted expansion
                            occurs within a word, the expansion of the
                            first parameter is joined with the beginning
                            part of the original word, and the expansion
                            of the last parameter is joined with the last
                            part of the original word. When there are no
                            positional parameters, "$@" and $@ expand to
                            nothing (i.e., they are removed).

                            Not extraordinarily enlightening, maybe, but better than sitting in the
                            dark, lighting your farts. :-D (Hit "q" to exit man.)

                            Basically what this means is that $@ will become the positional
                            arguments that you pass to your script. You can play with this by
                            writing a simple bash script like this

                            #!/bin/bash
                            echo $@

                            and passing it args to see what it echos. (Remember to chmod +x it..)

                            So, long story short, Yu-Xi Lim's bash script echos your package names
                            to the /path/to/manual_install. log file (">>" in bash means "append the
                            output of the command to the left to the file on the right",) then it
                            calls aptitude with those same package names.

                            It's simple, short, and to-the-point. The equivalent python script
                            would be much longer, for no appreciable gain. I write most of my tiny
                            little helper scripts in python, but in this case, bash is the clear
                            winnar. (And on *nix. man pages are your best friend. Plus you get to
                            feel all l33t when you grok them. lol)

                            Peace,
                            ~Simon

                            Comment

                            • John Salerno

                              #15
                              Re: outputting a command to the terminal?

                              Simon Forman wrote:
                              It's simple, short, and to-the-point. The equivalent python script
                              would be much longer, for no appreciable gain. I write most of my tiny
                              little helper scripts in python, but in this case, bash is the clear
                              winnar. (And on *nix. man pages are your best friend. Plus you get to
                              feel all l33t when you grok them. lol)
                              Thanks for the info! I might grudgingly decide to use a bash script in
                              this case. :)

                              And yes, it seems every time I ask a Linux question, everyone points me
                              to a man page. Sometimes I find them difficult to decipher, but they are
                              still a great help.

                              Comment

                              Working...