how do i start commands in new terminals in BASH script - bash

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?)

Related

Redirect xterm to a background for a headless machine

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.

Close a Terminator terminal opened from bash when the program in it exits

I have a udev rule that calls a script whenever I insert a certain USB device. That script launches a terminal using the following command:
terminator -e "...some_program" & exit
(Could have also been xterm, doesn't matter as far as I can tell.)
Once 'some_program' finishes doing what it should, it exits (from inside that program, not the bash), but the terminator terminal remains open, unless I Ctrl+C it, in which case it closes. But I don't want to Ctrl+C it, that's the whole point.
I have another udev rule that operates when the USB device is removed. But that rule won't trigger until the terminal that was opened from the
'insert usb rule' closes (even though I used & exit after launching the script from the 'insert usb rule')
I don't have anymore ideas and I've searched high and low for a solution. But nothing worked.
I tried sending SIGINT from inside some_program instead of using exit(1), it didn't work. The program terminated, but the terminal stayed open.
I tried killing the terminal by getting its PID and killing it. It didn't work.
I tried opening another terminal and killing the PID from there, it didn't work.
You might want to try this:
terminator -e "bash -c 'yourcommand'"
At least when I call ls this way it automatically closes:
# this closes automatically:
terminator -e "bash -c 'ls'"
# to test, this closes when the less command is ended (eg. by hitting q):
terminator -e "bash -c 'ls | less'"
Apparently terminator doesn't initialize it's own shell this way and as soon as the command passed with the -c option ends, the shell is terminated and terminator automatically closes the window.
Solved it. no need use 'bash -c'.
'some_program' is a ROS node, so all i needed to do is kill the rosmaster...
$ killall -9 rosmaster
and it works now.

Multiple tabs and Bash scripting

I am trying to open multiple tabs and execute a series of commands in each tab. Lets say I open 3 tabs tab1, tab2, tab3. Then in each tab I would like to execute following:
ssh user#address (PublicKey Authentication is setup and
hence no need to enter password)
Launch python scripts (python some.py)
Hold the tab open after executing the commands to see the outputs.
I went through some threads and have a rough outline for Bash script.
#!/bin/bash
echo "Script running"
gnome-terminal -e "bash -c \"ssh user#address; uname -a; exec bash\""
When I run the above script, a new terminal opens and I can see that I have ssh-ed into the target address but the other command uname -a didnot execute.
I would like to build upon this to implement the following:
Open multiple tabs and run commands. Ex : gnome-terminal --tab -e
"bash -c \"ssh user#address; python file1.py; exec bash\"" -tab -e
"bash -c \"ssh user#address; python file2.py; exec bash\""
Wait for one of the python file to start executing before opening
another tab and repeating the process for another python file.
Also is there a better way to implement the same task ?
The above code snippet was from this thread.
You should consider using screen or tmux or a similar terminal multiplexer for this.
Example usage:
screen -d -m bash -c 'ls; bash'
to initiate a screen session in which ls was executed and then a shell started, and then
screen -X screen bash -c 'date; bash'
to create a new window in the existing screen session, run date therein and then start a shell in that window.
Mind that the programs are run without you seeing their output right away on your controlling terminal. You can then attach to the screen session using
screen -x
Which attach you to the running session and will show you one of the screen windows (the virtual terminals of your two running programs). Typing Ctrl-A n will switch through the windows, Ctrl-A d will detach you again, leaving the programs running, so you can attach later with screen -x.
You can attach from several locations (e. g. from two different Gnome-terminals) to the same running windows. Both will then show the same contents.
Another advantage of using screen is that you can log out and the programs keep running. If you later login again, you can still attach to the running sessions.
Only a direct attack like a reboot, a kill-signal or an interaction (like pressing Ctrl-C while being attached) will terminate your programs then.

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.

Unix - Suppress informatory messages

I am trying to execute a remote command for one of my scripts. I have to run this script across many servers. so i will put it in a script. What I am trying to do is
ssh root#10.158.42.12 nohup perl /script/myscript.pl 06/04/2014 60 &
The script runs just fine but there is an info message which is displayed whenever you try to login . The one many of you would be familiar with ..
|-----------------------------------------------------------------|
| This system is for the use of authorized users only. |
| Individuals using this computer system without authority, or in |
Due to this the script execution is haulted unless an enter is pressed. I want to put the script in a cronjob for automatic execution, so i dont need to see this info message.
Here's my theory:
Your command doesn't run the program in the background on the server. It runs runs the program in the foreground on the server, and then you background ssh.
Since ssh runs in the background, you are immediately returned to your prompt.
Milliseconds later, ssh overwrites your prompt with this message and runs the command.
You are now looking at the ssh message and no prompt.
You hit press enter, which causes the prompt to be redrawn on the next line.
This leads you to believe ssh was actually waiting for you to press enter. In reality, the command was already run, and bash was ready for new commands, just obscured by ssh noise.
How to test:
If I'm right, pressing Ctrl+L instead of Enter will clear the screen and show the bash prompt. (assuming you don't use bash's vi mode).
If I'm not, Ctrl+L will instead either do nothing, print the ssh message again or just write ^L to the screen.
How to fix if I'm right:
ssh -f root#10.158.42.12 'nohup perl /script/myscript.pl 06/04/2014 60 &' 2> /dev/null

Resources