-2

I'm running an old Fortran code as part of a bash script. It completes the execution of its main purpose and then writes this to stdout and hangs:

FORTRAN PAUSE  
PAUSE prompt> To continue from background, execute 'kill -15 2658

I don't have access to the source code, but from this it looks like it's executing a FORTRAN PAUSE statement and waiting for user input. I expected to be able to do something like this to redirect stdin to it to get it to proceed:

my_fortran_code <<EOF
go
EOF

but no luck. It still just hangs with the same message.

If I could just automatically terminate it somehow after it gets to the PAUSE and proceed with the rest of the bash script that would be great. Any ideas?

EDIT

It's run on a remote machine that I can't log into and manually kill it by the pid. The runtime is important, and I can't just wait X minutes expecting a termination by that time. I'm guessing some kind of wrapper that runs this as a subprocess or thread and reads the text output and kills it may be the way to go...

Brian
  • 1,988
  • 1
  • 14
  • 29

2 Answers2

3

It actually tells you what needs to be done, you need to run kill -15 2658.

Open another bash terminal and run it, and it should continue.

It's mentioned in the docs you linked, at this part:

If stdin is not a tty I/O device, PAUSE displays a message like this:

PAUSE: To resume execution, type: kill -15 pid

where pid is the process ID.

Example: stdin not a tty I/O device:

demo% a.out < mydatafile
PAUSE: To resume execution, type: kill -15 20537
demo%

For the above example, type the following command line at a shell prompt in some other window. The window displaying the message cannot accept command input.

demo% kill -15 20537
Eric
  • 5,686
  • 2
  • 23
  • 36
  • It's on a randomly assigned compute node that I don't have direct access to after the job is started. Any idea how to do that automatically from within the same bash script? – Brian Aug 13 '21 at 04:15
  • Hmmm that's a different problem, I'd suggest to read the output and maybe send it into another bash call. You will need to run this in background, to make it parallel. Or maybe `expect` might be able to help. – Eric Aug 13 '21 at 04:20
  • Thanks I was hoping I was making it more complicated than it was, but it seems like maybe I was on the right track haha – Brian Aug 13 '21 at 04:23
  • 1
    You can run it under `expect` and look for the PAUSE message. It seems it would be better if you could rearrange the code so that it does get access to a TTY on stdin, but maybe that's infeasible. – tripleee Aug 13 '21 at 04:26
  • Or, as a simple and very crude workaround, run it in the background, get the PID, sleep for a safe amount of time, then send the signal on the assumption that it must have reached the PAUSE by then. `fortrancode & pid=$!; sleep 600; kill -15 "pid"` assumes 10 minutes should suffice. – tripleee Aug 13 '21 at 04:29
0

I was hoping for a simple solution, but alas here I am. I wrote a Python wrapper to kill the process when it detects "FORTRAN PAUSE" in the output stream. It's based on the answer here, but upgraded to Python 3 adapted for my purposes:

#!/usr/bin/env python3.9
import sys
import os
import subprocess

print('len(sys.argv):', len(sys.argv))
if len(sys.argv) == 1:
    print(
        '''This script wraps a command and waits until the output contains "FORTRAN PAUSE" then kills the process.
        
Syntax: 
    skip_fortran_pause.py compiled_fortran_program
'''
    )
    sys.exit(0)

print('Running "{}" until "FORTRAN PAUSE" is detected...'.format(sys.argv[-1]), flush=True)


run = sys.argv[-1]
log = ""
process = subprocess.Popen(run, stdout=subprocess.PIPE, shell=True)
while True:
    out = process.stdout.read(1).decode('utf-8')
    if out=='\n':
        # indent the wrapped function
        out = '\n    '
    log += out
    print(out, end='', flush=True)
    if (out == "") and (process.poll() is not None):
        break
    if "FORTRAN PAUSE" in log:
        print('\n"FORTRAN PAUSE" detected. exiting {}... ', flush=True, end="")
        process.kill()
        process.terminate()
        print("done.", flush=True)
        break
Brian
  • 1,988
  • 1
  • 14
  • 29