I have written a Fortran program (let's call it program.exe) with does some simulation for me. Via ssh I'm logging ino some far away computers to start runs there whose results I collect after a few days. To be up-to-date how the program proceeds I want to write the shell output into a text file output.txt also (since I can't be logged in the far away computers all the time). The command should be something like
nohup program.exe | tee output.txt > /dev/null &
This enables me to have a look at output.txt to see the current status even though the program hasn't ended its run yet. The above command works fine on my local machine. I tried first with the command '>' but here the problem was that nothing was written into the text file until the whole program had finish (maybe related to the pipe buffer?). So I used the workaround with 'tee'.
The problem is now that when I log into the computer via ssh (ssh -X user#machine), execute the above command and look at output.txt with the VI editor nothing appears until the program has finished. If I omit the 'nohup' and '&' I will not even get any shell output until it has finished. My thought was that it might have to do something with data being buffered by ssh but I'm rather a Linux newbie. For any ideas or workaround I would be very grateful!
I would use screen utility http://www.oreillynet.com/linux/cmd/cmd.csp?path=s/screen instead of nohup. Thus I would be able to set my program to detached state (^A^D) reconnect to the host, retrieve my screen session (screen -r)
and monitor my output as if I never logged out.
Related
I want to do the following thing: I want to replace the systemd program on my CentOS 7 installation, with a script, that will eventually start a shell where the user can input commands as root on the system console.
For this, I used the init=/sbin/myInit parameter. In this script I do some initialization, and in the end I call bash to enable the user to input commands. The interactive bash always appears on the screen.
Unfortunately, there is a problem with the input, that I haven't been able to solve: the input doesn't work correctly. When I press enter, only the second enter works, but no new line is performed on the screen. And when I type some characters, not all the characters are read. It seems like the console is in some Unicode mode (stty -a shows iutf8 parameter), and bash cannot correctly read the input. The output is fine, all the echo commands in my script are correctly printed on the screen (I only print ASCII characters).
I've tried all sorts of combinations, with different LC_ALL settings (LC_ALL=C, LC_ALL=C.utf-8, no LC_ALL or LANG variables initialization), redirect stdin/stdout/stderr to /dev/console, /dev/tty0 or /dev/tty1, the TERM variable is initialized to linux value, but nothing works. I tried unicode_start and unicode_stop commands, but unicode_stop doesn't work, and I get the error message "stty: standard input: unable to perform all requested operations". If I run showkey command, and I press the enter key, the correct keycode 28 is detected, same with normal boot.
Even stranger than this is the fact that if I'm using the init=/bin/bash kernel parameter, the input works fine, and if I manually run my script, it also works fine. If I copy the bash executable to something like /bin/mys, and I use init=/bin/mys, than same input problem occurs. It seems like the initrd image treats /bin/bash differently. Maybe it performs some initialization or something, that enables the bash to read correctly from the terminal. Why do we have this difference between init=/bin/bash and init=/bin/mys? It's the same executable in the end.
What am I doing wrong ?
As a general question about the init program, can somebody explain me what the init program should do to work correctly ? Any particular signals it has to respond to, any console initialization to be performed ?
I'm trying to solve this for days, and I cannot find any solution. On the web I couldn't find any article about this. So any suggestion would be greatly appreciated. Thank you.
I managed to pull a solution out for this one.
Turns out, at boot, the console is not initialized. I looked at the differences between the output of stty -a between the normal boot and the script boot (init=/sbin/myInit), and there are some differences between them: the console on normal boot had the following flags active on it: brkint ignpar ixon imaxbell isig icanon iexten echo, while when on script boot, those flags where cleared (stty reports them with - ). I'm not sure what they mean, except the echo flag, which I quickly noticed, because on each key press, no character ware printed on the screen.
So I decided to set those flags on my init script for /dev/console. After digging the stty manual page, I found the sane option, that sets the most important flags for normal console usage. So I added the line stty -F /dev/console sane in my init script.
But, there is a small problem. It seems that some console options cannot be changed by the stty command if the console is already opened by a process. So the first thing I did in my script is to redirect the stdin/stdout/stderr to /dev/null, via the line 0/dev/null, and then add the stty sane line, then redirect back the stdin/stdout/stderr to /dev/console.
I also noticed a process called plymouth, probably started by the CentOS initrd, so before the root was mounted and init script executed. I'm not sure if that process opened the system console, but I decided to eliminate it, by reconstructing a personalized initrd, by omitting the plymouth module from dracut (option -o plymouth).
After doing this, the script worked fine, and the bash process started by the script could read correctly the console.
Hope this helps somebody someday. Cheers
So, I have this interactive program that is running on an embedded linux ARM platform with no screen and that I cannot modify. To interact with it I have to ssh into the embedded linux distro, and run the program which is some sort of custom command line with builtin commands, and it does not exit, only SIGINT will quit the program.
I'm trying to automate it by letting it run in the background and communicate with it using pipes by sending SSH commands like this ssh user#host echo "command" > stdinpipe. This part works, I've been provided with an example like this in a shell script (I cannot use bash, I only have ash installed on the machine) :
#!/bin/sh
mkfifo somePipe
/proc/<PID>/exe < somePipe 2>&1 &
I can now easily command the program by writing to the pipe like
echo "command" > somePipe
and it outputs everything inside the terminal. The problem is that while it works if I have an SSH session open, it won't if I only send commands one by one as I said earlier (I'm using paramiko in python with the exec_command() method, just in case, but I don't think that is relevant, I could use invoke_session() but I don't want to have to deal with recv())
So I figured out I'd redirect the output of the program to a pipe. That's where problems arise. My first attempt was this one (please ignore the fact that everything is run as root and stored in the root home folder, that's how I got it and I don't have the time to make it cleaner now, plus I'm not the one managing the software) :
cd /root/binary
mkfifo outpipe
mkfifo inpipe
./command_bin &
# find PID automatically
command_pid=$(ps -a | egrep ' * \.\/command_bin *' | grep -v grep | awk '{print $1}')
/proc/${command_pid}/exe < inpipe 2>&1 &
echo "process ./command_bin running on PID ${command_pid}"
That alone works within the terminal itself. Now if I leave the SSH session open and open another terminal and type ssh root#host "echo command > /root/binary/inpipe" the code gets executed, but then it outputs the command I just typed and its result into the other terminal that stayed open. So it is obviously not an option, I have to capture the output somehow.
If I change ./command_bin & for ./command_bin >outpipe & the program never starts, I have no idea why, I know that because $command_pid is empty and I cannot find the process with ps -A
Now if instead I replace /proc/${command_pid}/exe < inpipe 2>&1 & with /proc/${command_pid}/exe < inpipe &>outpipe & the program starts, I can write to inpipe just fine with echo "command" > inpipe when the script finished running, however if I try any of cat < outpipe, tail outpipe it just hangs, and does nothing. I've tried using nohup when starting the command but it doesn't really help. I've also tried using a normal file for redirecting the output instead of a fifo, but with the exact same results.
I've spent the entire day on this thing and I cannot get it to work. Why is this not working ? Also I am probably just using an awful way to do this, is there any other way ? The only thing that's mandatory here is that I have to connect through ssh to the board and the command line utility has to stay open because it is communicating with onboard devices (using I2C, OneWire protocols etc).
To keep it simple I want to be able to write to the program's stdin whenever I want, get its stdout to go somewhere else (some file, buffer, I do not care) that I can easily retrieve later after an arbitrary amount of time with cat, tail or some other command with ssh.
I want to take continuous backup of logs being printed in my linux terminal. Is it possible that whenever something will be printed in my terminal, it will automatically get printed into some text file with time stamp.
Use the script command ie
script log.txt
at the start of your session. You can also add this to your bash profile so that it starts when you open a terminal etc. You need to use
script -a log.txt
to append. Don't try and cat it or tail it while in the session, you need to CTRL-D then have a look at what got logged.
I have a python script that I want run prior to any user logging in. This is for a home automation server and I want it always to be up and running as soon as the system allows.
I already have it in the rc.local file including an ampersand. This works.
But I can't see the screen output that it produces.
When I log into the unit (it's a raspberry pi running raspian) via SSH I can start it using screen which works the best as when I logout and back in, it's still there. AND I can see the output from the script.
But when I try running screen from the rc.local file, and subsequently login to check, the script isn't there (ie ps aux | grep script.py confirms)
edit: I've taken on Nirk's solution below about using tail. From the command line, it works fine. But starting it form within /etc/rc.local doesn't. I have touched the file and everyone has write access to it.
This is what's in my rc.local file:
python /home/pi/gateway.py &> /x10.log &
UPDATE
This is how I did it in the end:
Although the question was just about how to run in the background prior to login, there was more to it. The script is a work in progress and because of the way a particular serial device acts with it, it is/was prone to crashing (I've almost got all the bugs out of it). I needed to be able to restart it as well. I tried nohup but for some reason, it wouldn't keep it alive so in the end I found the top answer from this page got it all sorted.
In my /etc/rc.local I included a shell script to run:
nohup /home/pi/alwaysrun.sh > /home/pi/mha.log 2>&1 &
alwaysrun.sh contains:
#!/bin/bash
until python /home/pi/gateway.py; do
echo "'gateway.py' exited with exit code $?. Restarting..." >&2
sleep 1
done
nohup will keep the alwaysrun.sh script alive, and that in turn keeps my gateway.py script running. The redirect of stdout and stderr means I can setup a tail (and/or go back and check) the log.
Instead of using screen, if you just want to see the output you should redirect the output of the command to a log file and then tail the file.
I've got a program running in a GNOME Terminal, but the screensaver is acting up and won't let me back in with my password. While waiting for a fix for the gnome-screensaver bug, is there some way to see the output (or even take over the process) in a virtual console (Ctrl-Alt-F1) without being able to interact with the GNOME Terminal?
Clarification: The original issue was the screensaver, but the question I'd like answered is how to see the output from a process running in another terminal, after starting the process without any logging to file. I'm guessing it should be possible to set the output device of a process from a different shell? Or is it possible to put a process in another shell into background mode, and get it into the foreground in the current shell? Or even ask GNOME Terminal to redirect or copy the output?
I've had luck in the past killing the screensaver from a virtual console, unlocking X session.
# Get the pid (xscreensaver, gnome-screensaver, etc.)
ps -f -u $(whoami) | grep screensaver
kill -9 12345 # Replace 12345 with the real pid
EDIT: Seems like this has been thought of, and you should use one of these commands, depending on which screensaver program you use:
xscreensaver-command -exit
gnome-screensaver-comand --exit
See the man page for those commands for more details.
Usual way is to pipe the output to a file, like program > program.log
Do tail -f program.log in another tab of Gnome console, and the same in the non-X console.
Alternatively, use tee to duplicate the output in the same console: program | tee program.log
ssh in to the box. kill the screensaver. su to become root and kill -9 if it's really acting up.
Usually Gnome-Terminal displays the output of one vty out of /dev. So just connect your console to that vty.
Launch program with screen.
Open another terminal, launch screen -x and you have two terminals acting like one. Try it, it's fun :)