Search code examples
pythonlinuxscriptingless-unix

Python shell script open less with +F option


I have the following Python script, all seems to work how I want it to, except for the following:

  • less opens with the option -F, this will follow the file like Tail would.
  • to inspect (move through) the file the user has to ctrl + c to send an interrrupt.
  • when sending the ctrl +c (interrupt) this gets send to the python script, which will terminate the less process.

Is there a way to be able to use ctrl +c in the less window and not terminating the script while doing this?

#!/usr/bin/python
import sys
import os
import subprocess as sp
try:
    if(len(sys.argv) < 2):
        print "Choose an EngineID!"
    engineID = sys.argv[1]

    logdir='/data/work/silverlocal-%s/log' % engineID
    logfiles = sorted([ f for f in os.listdir(logdir) if f.startswith('log-%s' % engineID)])
    lastlog = (logdir + "/" + logfiles[-1])

    os.spawnlpe(os.P_WAIT, 'less', 'less', '+F', '-K', (lastlog), os.environ)

except KeyboardInterrupt:
    pass

Should there not be a nice solution using my current script, maybe someone can advice me a more suitable solution, language does not matter much.

Cheers,

Phillip

SOLUTION:

#!/usr/bin/python
import sys
import os
import subprocess as sp
import signal

if(len(sys.argv) < 2):
print "Choose an EngineID!"
engineID = sys.argv[1]

logdir='/data/awork/silverlocal-%s/log' % engineID
logfiles = sorted([ f for f in os.listdir(logdir) if f.startswith('log-%s' % engineID)])
lastlog = (logdir + "/" + logfiles[-1])
old_action = signal.signal(signal.SIGINT, signal.SIG_IGN)
os.spawnlpe(os.P_WAIT, 'less', 'less', '+F', (lastlog), os.environ)
signal.signal(signal.SIGINT, old_action)    # restore old signal disposition
print("I'm still running!")

Solution

  • You can try ignoring the SIGINT signal and remove the -K less option:

    #!/usr/bin/python
    import sys
    import os
    import signal
    import subprocess as sp
    
    try:
        if(len(sys.argv) < 2):
            print "Choose an EngineID!"
        engineID = sys.argv[1]
    
        logdir='/data/work/silverlocal-%s/log' % engineID
        logfiles = sorted([ f for f in os.listdir(logdir) if f.startswith('log-%s' % engineID)])
        lastlog = (logdir + "/" + logfiles[-1])
    
        old_action = signal.signal(signal.SIGINT, signal.SIG_IGN)
        os.spawnlpe(os.P_WAIT, 'less', 'less', '+F', (lastlog), os.environ)
        signal.signal(signal.SIGINT, old_action)    # restore old signal disposition
    except KeyboardInterrupt:
        pass
    
    print("I'm still running!")
    

    The try...except is no longer useful, so you could probably remove it.

    To be honest my recollection of signal handling is a bit foggy, and I'm not 100% sure why this works. Obviously ignoring SIGINT (generated by Ctrl+C) prevents Python acting on the signal, but the spawned process should inherit it parent's signal disposition. Possibly less sets up its own signal handlers, and maybe this is why it works.