Redirecting standard error for a cgi program

Is there any way to redirect standard error to standard out from within a Fortran program? This would make debugging a Fortran cgi script much easier, since error messages would be delivered directly to me, rather than burried among millions of lines of log messages. If you are not familiar with cgi scripts, note that shell redirection is not available. I understand this might be compiler dependent.

1 Like

I ran the following program on Windows with gfortran as the compiler:

! redir_stderr.f90 --
!     Redirect standard error?
!
program redir_stderr
    use iso_fortran_env

    implicit none

    write( error_unit, * ) 'Message 1'

    open( error_unit, file = 'redir.out' )

    write( error_unit, * ) 'Message 2'

end program redir_stderr

This does work - if I run it, only the first message appears on the screen and the second is written to a file.

I realised that I did not check if this works with a run-time error. So I tried with error stop":

  • It does not work correctly with gfortran - the output is still written to screen
  • It does work with Intel Fortran oneAPI.

So, indeed the results will be varied.

Some alternatives:

  • Open stderr to a file via a C routine (freopen, if I recall it correctly)
  • Do the actual processing in program A and call that from a program B (via execute_command_line and redirection). Program B is the one called as a CGI script.

Not sure on Windows but on Linux you should be able to:

  1. open a new terminal
  2. get the name of the terminal - run tty (e.g. /dev/pts/2 )
  3. and redirect your stdout/stderr output to it when running the script:
    exe 2>/dev/pts/2

The fortran unit numbers are just ordinary integers, so you can assign them to have any value that you want. Historically, something like

   nin = 5
   nlist = 6
   nerr = -1

might have worked. The units 5, 6, and -1 were often preconnected, but of course, this was not portable, so different preconnected unit values were needed on different computers (typically with conditional compilation using the de facto standard C preprocessor). Now with modern fortran, you might rather use something like

   use, intrinsic :: iso_fortran_env
   ...
   nin = input_unit
   nlist = output_unit
   nerr = error_unit

Then in your code when you get to the section where you want to merge the error and list output, you would do something like

   nerr_save = nerr
   nerr = nlist   ! this merges the outputs.
   ...
   ! computational section with errors here.
   write(nlist,...)  ! normal list output.
   write(nerr,...)  ! error output.
  ...
   nerr = nerr_save  ! this restores the error unit.

Someone suggested using an open() statement with the preconnected unit number to an external file. That might work, but the problem is that once the connection between the preconnected unit number and standard error has been broken, you probably can’t reconnect them, or at least not in any kind of standard-conforming way. With the above approach, you can merge and restore them several times if necessary.

1 Like