Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect xterm to a background for a headless machine

Tags:

bash

ubuntu

xterm

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

enter image description here

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.

like image 505
Tom Iv Avatar asked Mar 20 '21 19:03

Tom Iv


2 Answers

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.
like image 161
jurez Avatar answered Oct 25 '22 04:10

jurez


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.
like image 1
Bayou Avatar answered Oct 25 '22 02:10

Bayou