2

I have a script that runs for days, and inside it there's a counter. The counter gets written to a file periodically, is it possible to find out the value that the counter is set from either another python script, linux command, or even java?

Example of simple python counter:

import time
import random

a = 0
while True:
    a +=1
    time.sleep(random.random())

I'm interested in the value of a at a given time.

Leb
  • 15,483
  • 10
  • 56
  • 75

1 Answers1

1

Yes, you could use any IPC method e.g., you could send the counter over a socket:

self.request.sendall(json.dumps(dict(counter=a)).encode('ascii'))

If you want to get the value from an already running process that you can't modify then you could try to attach a debugger:

$ sudo gdb python <pid of running process>

To enable python-specific helper commands, add to your ~/.gdbinit:

add-auto-load-safe-path /path/to/python-gdb.py

The example gdb session could look like:

>>> thread apply all py-list

Thread 1 (Thread 0x7f68ff397700 (LWP 9807)):
   2    import random
   3    
   4    a = 0
   5    while True:
   6        a +=1
  >7        time.sleep(random.random())
>>> py-print a
global 'a' = 83

From another Python script, you could run gdb in the batch mode:

#!/usr/bin/env python
import shlex
import subprocess

cmd = shlex.split("sudo gdb --batch -ex 'py-print a' python") + [str(pid)]
output = subprocess.check_output(cmd, stderr=subprocess.DEVNULL,
                                 cwd=path_to_python_gdb)
a = int(output.rsplit(b'\n', 2)[-2].rpartition(b' ')[2])
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • I'm assuming it is, but is it harder to read from memory, if so how complicated will that be. Main reason is that the script has been running for a while now. – Leb Oct 05 '15 at 04:44
  • @Leb: do you mean that you have a running process that you can't modify? I've added a solution for a running process. – jfs Oct 05 '15 at 04:50
  • Yes the debugger seem closer to what I'm looking for. I tried looking at the commands through `help`, but how can I retrieve that variable? – Leb Oct 05 '15 at 05:05
  • @Leb: I've added an example gdb session. – jfs Oct 05 '15 at 05:13
  • What is `py-list` referring to? I'm getting `Undefined command:` for it – Leb Oct 05 '15 at 05:16
  • @Leb: look at `PyList` class in `python-gdb.py` – jfs Oct 05 '15 at 05:19
  • A program activity like doing IPC might terminate the sleep with EINTR. (There is a related PEP 0475) – VPfB Oct 05 '15 at 06:40
  • @VPfB: I meant that the server is running in another thread and therefore it has no effect on the sleep. Or do you mean that something [sends signals to the process e.g., to start an interactive Python console](http://stackoverflow.com/a/4693529/4279)? – jfs Oct 05 '15 at 06:46
  • @J.F.Sebastian: I was referring to the first paragraph of your answer. An interrupted sleep might remain unnoticed in the example counter code. That's why I have added a small note. Of course, using separate threads will prevent that. – VPfB Oct 05 '15 at 07:41
  • @VPfB: my comment is also about the first paragraph: I don't see how a socket server (or any non-signal-based ipc method) would interrupt the sleep here. I assume the actual code that OP uses is more complex. Though I agree EINTR may be a source of subtle non-local bugs. – jfs Oct 05 '15 at 12:27
  • @J.F.Sebastian: Your first paragraph mentions "any IPC" and after reading the question, on the top of my mind there was the way the standard dd utility reports its progress (kill -USR1). Sure there are many other solutions, that's why I wrote 'might terminate'. – VPfB Oct 05 '15 at 13:30
  • @VPfB: we are in agreement here. I even linked in the comment above [the answer that uses SIGUSR2 to start an interactive Python console within a running process.](http://stackoverflow.com/a/4693529/4279) – jfs Oct 05 '15 at 14:40