Redirect xterm to a background for a headless machine - bash

I have a application that launches xterm and dumps uart logs. I am able to see it launch and dump the logs in the GUI. However, Using a remote session I want the xterm output to be running as a background process somewhere so that I can switch back and forth within a single terminal.
Using GUI
Using remote terminal (SSH)
$ xterm
xterm: Xt error: Can't open display: :0
I tried to do something like, but failed to work -
alias xterm="/bin/bash -c"
I don't want to have X forwarding and launch a window on my local machine as well.

If you just need the logs, you most likely don't need an X server or xterm.
You can simply run the target command itself. From your screenshot it looks like the command might be telnet 127.0.0.1 <port_number>. You can find it from the script that your application launches, or with ps -ef when it's running. If it's an UART, then you can also use minicom or socat to connect directly to serial port without any extra programs. This way, you don't even need telnet.
You can combine this command with either screen or tmux so that it's running in the background and you can switch to it from any terminal or console. Just run screen with no arguments, then run the command on virtual screen. Detach with CTRL-a d, and your command will continue to run in the background ready for you to reconnect to it at any time with screen -r.
Moreover, screen can also connect to serial port directly so you get two for the price of one.
The thing with xterm is that it will not write the logs anywhere except in the graphics buffer, and even there it will be only as flashing pixels which is not suitable for any processing. If you insist on going that way, you have several options:
Change the script that application runs (might not be possible depending on your situation)
Replace /usr/bin/xterm with your dummy script that just runs bash instead of xterm, and redirects the output to a file (ugly, but you could probably avoid breaking other applications by changing PATH and putting it somewhere else). In your script, you can use bash's redirection features such as >, or pipe output to tee.
Start a VNC server in the background and set the DISPLAY environment variable when you run your application to the number of virtual screen. In this case, any windows from application will open on VNC virtual screen and you can connect to it as you please.
Use xvfb as a dummy X server and combine it with xterm logging, etc.

Solution 1: Fake xterm on X11-less systems
You can also create a wrapper script that replaces xterm with another function. Test this out on a laptop with X11:
$ function xterm {
echo "hello $#"
}
$ xterm world 1
hello world 1
$ export -f xterm
$ /bin/xterm # opens a new xterm session
$ xterm world 2 # commands executed in second terminal
hello world 2
This means that you've replaced the command xterm for a function in all of the child processes.
Now, if you already know that your script will work in a terminal without xterm, you could create a function that accepts all of the parameters and executes it. No need for complicated screen stuff or replacing /usr/bin/xterm.
Solution 2: Dump UART data for the winz
If you want to save all of the uart data into a file, this is easily fixed by creating a screen session and a log file. Below the command will create a session named myscreensessionname that listens on the serial connection /dev/ttyUSB0 and writes its data to /home/$USER/myscreensessionname.log.
$ screen -dmS myscreensessionname -L -Logfile /home/$USER \
/myscreensessionname.log /dev/ttyUSB0 115200
Note that if you're going to use multiple screen sessions, you might want to use serial ids instead of /dev/ttyUSB0. You can identify the connections with udevadmin as follows.
$ udevadm info --name=/dev/ttyUSB0 | grep 'by-id'
S: serial/by-id/usb-FTDI_TTL232R-3V3_FTBDBIQ7-if00-port0
E: DEVLINKS=/dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTBDBIQ7-if00-port0 /dev/serial/by-path/pci-0000:00:14.0-usb-0:4.4.4.1:1.0-port0
Here, instead of /dev/ttyUSB0, I would make use of /dev/serial/by-id/usb-FTDI_TTL232R-3V3_FTBDBIQ7-if00-port0.
EDIT:
You can attach the screen session with the following command. Once in the screen session, press crtl+a, and press d to detach.
$ screen -Dr myscreensessionname
To view all of your screen sessions:
$ screen -list
There is a screen on:
2382.myscreensessionname (04/02/2021 10:32:07 PM) (Attached)
1 Socket in /run/screen/S-user.

Related

Send and read serial commands from terminal

I have a very limited list of software that I can install on an (IOT edge) device. I have minicom and chat commands (in addition to standard commands like echo and cat), and need to write to a serial device a command and read the response.
The device in question is a modem, and I need to run AT commands on it. If using minicom and setting up the menu etc. I can run these commands normally, and get the output. The problem is that I have around a thousand of these devices, so setup and data logging needs to be automated.
So within these parameters is there a way to run minicom and capture the output without any interactive elements? I have tried
minicom -S scriptfile -C outfile
where scriptfile (for now) contains following:
sleep 1
send "AT"
This seems to ignore the sleep command, and outfile is created, but is left empty. Also what would I need to add to the command that it wouldn't open a session or interactive element?

Pass command from scheduled script to program running in xterm window

I have a game server running in an xterm window.
Once daily I'd like to send a warning message to any players followed after a delay by the stop command to the program inside the xterm window from a script running on a schedule. This causes the cleanup and save functions to run automatically.
Once the program shuts down I can bring it back up easily but I don't know how to send the warning and stop commands first.
Typed directly into xterm the commands are:
broadcast Reboot in 2 minutes
(followed by a 2 minute wait and then simply):
stop
no / or other characters required.
Any help?
Do you also need to type something from the xterm itself (from time to time) or do you want your server to be fully driven from external commands?
Is your program line-oriented? You may first try something like:
mkfifo /tmp/f
tail -f /tmp/f | myprogram
and then try to send commands to your program (from another xterm) with
echo "mycommand" > /tmp/f
You may also consider using netcat for turning your program to a server:
Turn simple C program into server using netcat
http://lifehacker.com/202271/roll-your-own-servers-with-netcat
http://nc110.sourceforge.net/
Then you could write a shell script for sending the required commands to your "server".
If you know a little about C programming; I remember having once hacked the script program (which was very easy to do: code is short) in order to launch another program but to read commands from a FIFO file (then again a shell script would be easy to write for driving your program).
Something you might try is running your program inside a screen session.
You can then send commands to the session from cron that will be just
as if you typed them.
In your xterm, before launching the program do:
screen -S myscreen bash
(or you can even replace bash by your program). Then from your cron
screen -S myscreen -X stuff 'broadcast Reboot in 2 minutes\n'
sleep 120
screen -S myscreen -X stuff 'stop\n'
will enter that text. You can exit the session using screen -S myscreen -X quit
or by typing ctrl-a \.
screen is intended to be transparent. To easily see you are inside screen, you can
configure a permanent status bar at the bottom of your xterm:
echo 'hardstatus alwayslastline' >~/.screenrc
Now when you run screen you should see a reverse video bottom line. Depending
on your OS it may be empty.

Cannot successfully disconnect from remote machine using 'nohup' or 'screen'

I am trying to do some work on a remote machine and disconnect without terminating the work. I have tried both nohup and screen, unfortunately it is not working out. After I type exit to logout my work also terminates immediately.
I am trying to run 108 simulations on a remote machine. For that purpose I have written a script named batch.sh which runs one simulation after the other until all 108 are done. The program that actually runs a simulation launches 5 programs in 5 different terminals (using xterm -e). I run batch.sh using:
nohup bash batch.sh &
As long as I am connected everything works just fine. If I disconnect and then reconnect to check whether everything is working as it should...no joy :(
Are there any caveats I am overlooking? Possibly because my program launches other programs in external terminals?
UPDATE
If I use the suggestions of adding -oForwardX11=no to ssh and unset DISPLAY before launching my script I get these errors:
nohup: ignoring input and appending output to nohup.out
In nohup.out I have these messages:
xterm Xt error: Can't open display:
xterm: DISPLAY is not set
Apparently your script/program is trying to launch xterm on its own. These days many systems enable X11 forwarding for their SSH client by default - as a result the DISPLAY variable is set in your shell session but becomes invalid once you disconnect. Therefore, as long as you are connected to the remote system, the xterm processes can access the X server on your local machine through the SSH connection, but die once that connection is severed.
I have occasionally encountered the same issue with Java programs that use e.g. the Java AWT subsystem to generate image files, even when there is no actual graphical window. You should first see if your program will somehow adapt if there is no X server available. One option is to disable X11 forwarding with the -oForwardX11=no option to ssh:
$ ssh -oForwardX11=no user#server.host.name
You could also try unsetting the DISPLAY environment variable before starting your script and see what happens.
However, if your program is launching xterm windows indiscriminately then you'd have to make it e.g. use an output file on the server instead - by modifying it, if necessary. As an added advantage, you would get rid off the network load and timing overhead involved with forwarded X connections.
If you cannot change the way your program works and you do not actually care about the output in those xterm windows, then you could try launching a virtual framebuffer X server on the remote system and have your script use that for xterm.

Buffered pipe in bash

I'm running a Bukkit (Minecraft) server on a Linux machine and I want to have the server gracefully shut down using the server's stop command and the computer suspend at a certain time using pm-suspend from the command line. Here's what I've got:
me#comp~/dir$ perl -e 'sleep [time]; print "stop\\n";' | ./server && sudo pm-suspend
(I've edited by /etc/sudoers so I don't have to enter my password when I suspend.)
The thing is, while the perl -e is sleeping, the server is expecting a constant stream of bytes, (That's my guess. I could be misunderstanding something.) so it prints out all of the nothings it receives, taking up precious resources:
me#comp~/dir$ ...
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>...
Is there any such thing as a buffered pipe? If not, are there any ways to send delayed input to a script?
You may want to have a look at Bukkit's wiki, which recommends an init script for permanently running servers.
This init script uses rather unconventional approach to communicate with running server. The server is started in screen session, then all commands are send to the server console via screen, e.g.
screen -p 0 -S $SCREEN -X eval 'stuff \"stop\"\015'
See https://github.com/Ahtenus/minecraft-init/blob/master/minecraft
This approach suggest that bukkit may be expecting standard input to be attached to a terminal, thus requiring screen wrapper (which is itself terminal emulator) for unattended runs.

how do i start commands in new terminals in BASH script

my bash script reads in a few variables and then runs airodump on my home network. I would like to keep the window with airodump running and open some new terminals to run other commands for network discovery while the airodump screen is open (so i can see the results).
right now what i have looks like this (edited for brevity):
#!/bin/bash
read -p "Enter the channel: $channel"
airomon-ng start wlan0 $channel,$channel
airodump-ng -c $channel,$channel mon0 &&
terminator -e netstat -ax &&
terminator -e nmap 192.168.1.1
the first command that uses the whole terminal (airodump) starts up fine and i can see the network, but then it just stays on that screen. If i ctrl+c then it goes back to prompt but i can see the error : Usage: terminator [options] error no such option
i want the netstat and nmap commands to appear and stay in their own terminal windows, how can i do this?
The terminal window is generated by a separate program from the command running inside. Try one of these variations:
xterm -e airomon-start wlan0 "$channel","$channel" &
gnome-terminal -x airomon-start wlan0 "$channel","$channel" &
konsole -e airomon-start wlan0 "$channel","$channel" &
Pick the command that invokes the terminal program you like. You'll have to do this for every command that you want run in its own window. Also, you need to use a single & at the end of each such command line -- not a double && -- those do totally different things. And the last line of your script should be just
wait
that makes it not exit out from under all the terminals, possibly causing them all to die.
Obligatory tangential shell-scripting nitpick: ALWAYS put shell variable uses inside double quotes, unless you know for a fact that you need word-splitting to happen on a particular use.
If the script is running in the foreground in the terminal, then it will pause while an interactive command is using the terminal. You could change the script to run airodump in a new terminal as well, or you could run the background commands before you start airodump (maybe after sleeping, if you're concerned they won't work right if run first?)

Resources