| 
431
 | 
     1 #!/usr/bin/env python
 | 
| 
 | 
     2 
 | 
| 
 | 
     3 """
 | 
| 
 | 
     4 attach strace to a process:
 | 
| 
 | 
     5 
 | 
| 
 | 
     6 624  sudo strace -p $(pidof firefox)
 | 
| 
 | 
     7 625  kill 6976
 | 
| 
 | 
     8 626  isrunning firefox
 | 
| 
 | 
     9 
 | 
| 
 | 
    10 Optionally kill the process when detached
 | 
| 
 | 
    11 """
 | 
| 
 | 
    12 
 | 
| 
 | 
    13 
 | 
| 
 | 
    14 import optparse
 | 
| 
 | 
    15 import os
 | 
| 
 | 
    16 import subprocess
 | 
| 
 | 
    17 import sys
 | 
| 
 | 
    18 
 | 
| 
 | 
    19 from subprocess import check_output
 | 
| 
 | 
    20 
 | 
| 
 | 
    21 def main(args=sys.argv[1:]):
 | 
| 
 | 
    22 
 | 
| 
 | 
    23     usage = '%prog [options] ProgramName_or_PID'
 | 
| 
 | 
    24     parser = optparse.OptionParser(usage=usage, description=__doc__)
 | 
| 
 | 
    25     parser.add_option('-k', '--kill',
 | 
| 
 | 
    26                       action='store_true', default=False,
 | 
| 
 | 
    27                       help="kill process after strace is done")
 | 
| 
 | 
    28     options, args = parser.parse_args(args)
 | 
| 
 | 
    29     if len(args) != 1:
 | 
| 
 | 
    30         parser.print_usage()
 | 
| 
 | 
    31         parser.error("Please specify program or PID to attach to")
 | 
| 
 | 
    32 
 | 
| 
 | 
    33     # get the PID
 | 
| 
 | 
    34     try:
 | 
| 
 | 
    35         pid = int(args[0])
 | 
| 
 | 
    36     except ValueError:
 | 
| 
 | 
    37         pid = check_output(["pidof", args[0]]).strip().split()
 | 
| 
 | 
    38         if len(pid) > 1:
 | 
| 
 | 
    39             parser.error("Multiple PIDs found for %s:\n%s" % (args[0],
 | 
| 
 | 
    40                                                               '\n'.join(pid)))
 | 
| 
 | 
    41         # TODO: handle not matching case
 | 
| 
 | 
    42         pid = int(pid[0])
 | 
| 
 | 
    43 
 | 
| 
 | 
    44     # invoke strace
 | 
| 
 | 
    45     subprocess.call(['sudo', 'strace', '-p', str(pid)])
 | 
| 
 | 
    46 
 | 
| 
 | 
    47     # kill if specified
 | 
| 
 | 
    48     os.kill(pid, 9) # TODO: better than SIGKILL
 | 
| 
 | 
    49 
 | 
| 
 | 
    50 if __name__ == '__main__':
 | 
| 
 | 
    51     main()
 |