redirect serial input from device to file in bash script - linux

I'm working with a device connected to my PC via serial port.
When i send a command to this device (using putty or minicom) it send me back some output.
I would like to save this output (serial input of my PC) on a local file.
I found this workaround to do this:
-In the first terminal i type:
cat -v /dev/ttyACM0 > filename
-In another terminal i type:
echo -ne 'cat "filename"\n\r' > /dev/ttyACM
It works, but i'd like to automate the process with a single bash script.
./serialDownload.sh filename
I tried to put in background the first command before executing the second one but it doesn't work...
#!/bin/bash
SERIAL_PORT="/dev/ttyACM0"
BAUDRATE=9600
stty raw speed $BAUDRATE
./serialListen.sh $1& (->this put in background the first command)
sleep 2
echo -e 'cat "'$1'"\n\r' > $SERIAL_PORT
Thank you in advance for any kind of help!

Related

How do i copy the output from ttyS0 to a file but still see it on ttyS0 in Putty

I can use this to send ttyS0 to a log.txt file at the beginning of the script
exec >> /mnt/Carousel_Games/systeminfo/pcuae-log.txt
exec 2>&1
thats ok but now it will not show ttyS0 on Putty, I can use this instead
exec >> /dev/ttyS0
exec 2>&1
And it will show it on Putty but not in the log.txt.
Is there a way of getting it to do both, show it on Putty plus send it to the log.txt file...?
Its so I can see it booting on ttyS0 and I can look at the log.txt file if I need too, if someone is having a problem with it booting properly, I can see it booting on there machine with the log.txt file they send me.
One way to do it is to open another terminal and tail your file in which the data is being written:
tail -f /mnt/Carousel_Games/systeminfo/pcuae-log.txt
Then, from 2nd terminal, run your command (or your script containing command):
exec >> /mnt/Carousel_Games/systeminfo/pcuae-log.txt
and your 1st terminal will show you what's being coming into the file.

How to connect input/output to SSH session

What is a good way to be able to directly send to STDIN and receive from STDOUT of a process? I'm specifically interested in SSH, as I want to do the following:
[ssh into a remote server]
[run remote commands]
[run local commands]
[run remote commands]
etc...
For example, let's say I have a local script "localScript" that will output the next command I want to run remotely, depending on the output of "remoteScript". I could do something like:
output=$(ssh myServer "./remoteScript")
nextCommand=$(./localScript $output)
ssh myServer "$nextCommand"
But it would be nice to do this without closing/reopening the SSH connection at every step.
You can redirect SSH input and output to FIFO-s and then use these for two-way communication.
For example local.sh:
#!/bin/sh
SSH_SERVER="myServer"
# Redirect SSH input and output to temporary named pipes (FIFOs)
SSH_IN=$(mktemp -u)
SSH_OUT=$(mktemp -u)
mkfifo "$SSH_IN" "$SSH_OUT"
ssh "$SSH_SERVER" "./remote.sh" < "$SSH_IN" > "$SSH_OUT" &
# Open the FIFO-s and clean up the files
exec 3>"$SSH_IN"
exec 4<"$SSH_OUT"
rm -f "$SSH_IN" "$SSH_OUT"
# Read and write
counter=0
echo "PING${counter}" >&3
cat <&4 | while read line; do
echo "Remote responded: $line"
sleep 1
counter=$((counter+1))
echo "PING${counter}" >&3
done
And simple remote.sh:
#!/bin/sh
while read line; do
echo "$line PONG"
done
The method you are using works, but I don't think you can reuse the same connection everytime. You can, however, do this using screen, tmux or nohup, but that would greatly increase the complexity of your script because you will now have to emulate keypresses/shortcuts. I'm not even sure if you can if you do directly in bash. If you want to emulate keypresses, you will have to run the script in a new x-terminal and use xdotool to emulate the keypresses.
Another method is to delegate the whole script to the SSH server by just running the script on the remote server itself:
ssh root#MachineB 'bash -s' < local_script.sh

Run a command from a script directly to another process

I'm currently working on a script which interact with another process.
If it is relevant, the said process is a simdebug console. What I want is exiting it properly because when I kill the process itself, it creates a lock file .lck.
The Simdebug console is waiting for inputs and closes on receiving quit, then q and n, both sperated by an enter keypress to validate the command.
I managed to send some commands to the Simdebug using
echo quit > /proc/< PID >/fd/1
But it only print the results of the echo and I can't find how to send a enter keypress, only new lines '\n' .
I can't aswell manage to send a quit command which would execute directly in the Simdebug and not the terminal where it is sent from.
My question would be resolved if one of those two points is answered:
Is it possible to simulate a validate keypress as in :
Term 1 : echo ifconfig ; echo < enter keypress>
Which would then execute what's in the read buffer of the Term 2
Is there a way to already execute a commande in another process as in
Term 1 : < unknown syntax > pwd
Term 2 < shows pwd of term2 not term1>
Which would not be working only from terminal to terminal but with an already opened process in read mode.
This is actually a hard thing to do. If you send characters to the /proc/self/fd/0 device or similar stdin device link from a different master terminal then it will just output the characters to the output side of the master terminal of the other process.
With tools like expect or pdip or screen you can send anything you want to a process encapsulated in their pseudoterminals as if it comes from their master terminal. But if a process is running then it will already have it's own terminal.
You can be in luck if your console can be persuaded for a controlling terminal transfer with reptyr.
For example if your console has process id 999999 (and you have screen and reptyr installed and maybe did something to appease selinux or apparmor/yama protections):
screen -dmS automateconsole
screen -S automateconsole -p 0 -X stuff 'reptyr 999999^M'
screen -S automateconsole -p 0 -X stuff 'quit^M'
sleep 1s
screen -S automateconsole -p 0 -X stuff 'q^M'
sleep 1s
screen -S automateconsole -p 0 -X stuff 'n^M'
sleep 1s
screen -S automateconsole -p 0 -X stuff 'exit^M'
But note:
You probably should cleanup the program that init'ed the console.
On Ubuntu at least I could not reptyr processes from other SSH sessions.
https://github.com/nelhage/reptyr
http://theterminallife.com/sending-commands-into-a-screen-session/

redirect the ouput of command into a socket on linux

I'm using netcat to connect to a server.
the problem is that i want to send somme non printable to the server caracters.
I wanted to achieve this with a command redirection in linux.
lets say this is the command: nc hostname port
so when i checked the file descriptors of the command nc in the folder: cd /proc/$(pidof nc)/fd is saw the there was another fd with number 3 that conserns the socket. 3 -> socket:[1675643]
the problem is that i wanted to redirect the output of let's say echo -ne '\xff\x0f\xab\xde' > ./3 to the socket.
I couldn't do so and the ouput is: bash: ./3: No such device or address
One cannot output something to a socket which is opened only by another process.
In order to first use interactive input/output and afterwards send the echo string, you can do:
(cat; echo -ne '\xff\x0f\xab\xde')|nc hostname port
(press the EOF character Ctrl-D to end your input and start the echo).

Replace login prompt with interactive bash script on serial port linux

I am working on a CentOS box.
What I expect: To run my own CLI/setup on startup instead of login prompt on serial console (telnet).
What I did so far:-
I changed call to "agetty" command in serial.conf and serial-ttyUSB0.conf files under /etc/init/, as follows:-
exec /sbin/agetty -n -l <path-to-my-custom-script> ........
My custom.sh script is:-
#!/bin/bash
LOOP_FLAG=0
while [ $LOOP_FLAG -eq 0 ]; do
for TTY in /dev/ttyS0 /dev/tty0; do
echo "Please choose to enter in 'setup' or 'cli'. (s/c)? " > $TTY
done
read sc
case $sc in
[Ss]* ) LOOP_FLAG=1; <some-executable-cli-file-path>; break;;
[Cc]* ) LOOP_FLAG=1; <some-executable-setup-file-path>; break;;
* ) for TTY in /dev/ttyS0 /dev/tty0; do
echo "Please press 's' or 'c'." >$TTY
done;;
esac
done
But when system boots, on a telnet session, I could only see the "Please choose to enter.." question on screen and after that I couldn't able to type anything on console.
One more update:
If I run the above agetty command on shell prompt as it is (say from ssh session), then it works fine on serial console (telnet). But, from the above startup scripts, it doesn't work.
Can anybody help me out with this?
Thanks in advance.
-Neo
Sorry I'm a few years late. Hopefully this will be of help for people searching for solution to this problem in the future.
The issue lies here:
-n, --skip-login Do not prompt the user for a login name. This can be used in connection with -l option to invoke a non-standard login
process such as a BBS system. Note that with the -n option, agetty
gets no input from user who logs in and therefore won't be able to
figure out parity, character size, and newline processing of the
connection. It defaults to space parity, 7 bit characters, and ASCII
CR (13) end-of-line character. Beware that the program that agetty
starts (usually /bin/login) is run as root.
So you need to initialize the terminal yourself in the script you are replacing the login prompt with. I found the settings below work well:
/bin/stty -F /dev/ttyO0 115200 cs8 sane
Remember to replace the baud rate and terminal name to your own.

Resources