re1ro / grunt-bg-shell

Better shell commands for grunt
MIT License
50 stars 8 forks source link

Print output of python to console #18

Closed thinkh closed 8 years ago

thinkh commented 8 years ago

I created the following bgShell target to run the server as background script:

bgShell: {
    options: {},
    run_server: {
        cmd: 'python plugins/server',
        bg: true,
        fail: true
    }
}

When the python script print something to the console the output does not appear. However, when I set bg: false the python output is printed to the console.

Is there a way to print the output of a bg task to the console?

re1ro commented 8 years ago

@thinkh The reason why it's happening is your python application is trying to output right into console, not using stdout. Do you have other tasks in your bgShell config? You could run something else with bg: true and leave bg: false for run_server

Another thing you can try is running python with unbuffered stdout. I am not sure if it will work cmd: 'python -u plugins/server'

thinkh commented 8 years ago

Thanks for your reply. Unfortunately, I cannot use bg: false, because I'm using a file watcher that restarts the server every time a python file changes. And the file watcher requires a background task.

    watch: {
      server: {
        files: ['plugins/**/*.py'],
        tasks: ['bgShell:kill_server', 'bgShell:run_server'],
        options: {
          atBegin: true
        }
      }
    }

I also tried your other suggestion with cmd: 'python -u plugins/server'. However, this doesn't work either. The server does not even seem to start (not listed as process). Might be that it's a problem with our Flask server, but it is hard to debug without output. ;-) I also tried several other suggestions, which was not successful either.

If you or someone else still have an idea, let me know.

thinkh commented 8 years ago

I discovered an interesting behavior: If grunt bgShell run_server runs as last or single task, then the background process is created and grunt is terminated:

vagrant@box:/vagrant$ grunt bgShell:run_server
Running "bgShell:run_server" (bgShell) task

Done, without errors.

Execution Time (2016-09-23 08:17:20 UTC-0)
loading tasks  1s  ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 99%
Total 1.1s

vagrant@box:/vagrant$

There is no time to print the server output, because the stdout is already closed(?).

If I create a dummy file watcher that does nothing and run this as last task as following:

    watch: {
      foo: {
        files: ['bar'],
        tasks: []
      }
    },
//...
  grunt.registerTask('server', [
    'bgShell:run_server',
    'watch:foo'
  ]);

Then the console prints the python output and and is still open (i.e. the grunt task didn't terminate):

vagrant@box:/vagrant$ grunt server_restart

Running "bgShell:run_server" (bgShell) task

Running "watch:foo" (watch) task
Waiting...
08:20:59 INFO server.config: merging: plugins/core/config.json core
08:20:59 INFO server.config: merging: plugins/data_hdf/config.json data_hdf

The problem is now that I cannot watch my python files and start another foo watcher in that task list. Then I receive the output, but python file watcher is not running anymore...

thinkh commented 8 years ago

I found a solution that worked. I start the server process in an infinite loop with while true; do python plugins/server; sleep 1; done, which creates a new server process everytime the previous process has been killed. The file watcher simply kills the server process when a python file has changed. Keeping the server process in the infinite loop does the trick for printing the output.

re1ro commented 8 years ago

@thinkh Awesome! I am glad you've discovered the solution