pipe or send strings with socat/netcat with a pause - linux

i capture unbuffered codes from ttyUSB0 as an string though hexdump'ing
/usr/bin/stdbuf -o0 /bin/busybox hexdump -v -e '12/1 "%02x" "\n"' /dev/ttyUSB0
with example-output like this (without quotes): "20303830303e353a30373220"
Now i am helpless:
I want a loop to netcat/socat the first capture (maybe with read ?) to another host, than a slight pause e.g 10 sec before the next capture is send.
i searched for an elegant line with socat, but all my piping-examples failed. Seems some problems of understanding the subshell-processes.. and lack of experience. anybody a hint?

The following works for me with my mouse as input:
sudo stdbuf -o0 hexdump -v -e '12/1 "%02x" "\n"' /dev/input/by-id/usb-Logitech_USB_Receiver-if02-mouse | (while true; do read buf; echo $buf; sleep 1; done) | nc localhost 8008
I believe there could be a better implementation of what I do in the while-loop...
I'm able to get the input from my mouse with a previously-started
nc -l localhost 8008

Related

Bash - Grepping nc output in a for loop

I'm currently trying to grep the output for a nc in a bash single line loop, to only show me lines with openstring within. I've already tried --line-buffered with no success. Can anybody give me a light about what I'm doing wrong? Here goes the command:
root#kali:~# for host in $(seq 200 254); do nc -nvv -w 1 -z 192.168.15.$host 80 | grep --line-buffered "open"; done
Redirect stderr to stdout so you can grep it.
You can do that by putting 2>&1 anywhere between do and |.

inotify + stdout piping - output being lost in a pipe

I have some one-liner generating events for inotify.
while true; do for i in $(seq 1 100); do touch /tmp/ino/foo$i; sleep 1s; done; rm /tmp/ino/foo*; done
I then set up a small bash pipeline to watch that folder, ignoring events about ISDIR (maybe I could do that with inotifywait, but that's not relevant):
inotifywait -m -e close /tmp/ino 2>/dev/null | grep -v ISDIR
And that works fine, I see lines like /tmp/ino/ CLOSE_WRITE,CLOSE foo57.
But if I add an extra pipe at the end, I don't get any output. To keep it simple, let's use the fact that grep pattern is idempotent.
inotifywait -m -e close /tmp/ino 2>/dev/null | grep -v ISDIR | grep -v ISDIR
This produces no output. I know the my generator is still running, and a pipeless inotifywait -m -e close /tmp/ino in another terminal is still producing output.
After a bit of thinking, I assumed it was probably a buffering problem (issues like this often seem to be). I changed my pipeline to
inotifywait -m -e close /tmp/ino 2>/dev/null | grep -v ISDIR --line-buffered | grep -v ISDIR
And now I'm getting output again, so that fixes the problem.
However, I don't really understand why it failed to work without forcing line buffering. I've never experienced issues like this with grep, even with 'slow producing' outputs.
However, some other programs in the pipeline, forcing sed to be sed -u , and forcing me to add fflush() in at the end of each awk statement.
So, what's forcing strange buffering here, and how can I fix it (without having to scrabble around in man pages looking for esoteric force line buffering commands)?
inotifywait is probably buffering. I would have suggested using stdbuf:
stdbuf -oL inotifywait -m -e close /tmp/ino 2>/dev/null | grep ...

pseudo-terminal error will not be allocated because stdin is not a terminal - sudo

There are other threads with this same topic but my issue is unique. I am running a bash script that has a function that sshes to a remote server and runs a sudo command on the remote server. I'm using the ssh -t option to avoid the requiretty issue. The offending line of code works fine as long as it's NOT being called from within the while loop. The while loop basically reads from a csv file on the local server and calls the checkAuthType function:
while read inputline
do
ARRAY=(`echo $inputline | tr ',' ' '`)
HOSTNAME=${ARRAY[0]}
OS_TYPE=${ARRAY[1]}
checkAuthType $HOSTNAME $OS_TYPE
<more irrelevant code>
done < configfile.csv
This is the function that sits at the top of the script (outside of any while loops):
function checkAuthType()
{
if [ $2 == linux ]; then
LINE=`ssh -t $1 'sudo grep "PasswordAuthentication" /etc/ssh/sshd_config | grep -v "yes\|Yes\|#"'`
fi
if [ $2 == unix ]; then
LINE=`ssh -n $1 'grep "PasswordAuthentication" /usr/local/etc/sshd_config | grep -v "yes\|Yes\|#"'`
fi
<more irrelevant code>
}
So, the offending line is the line that has the sudo command within the function. I can change the command to something simple like "sudo ls -l" and I will still get the "stdin is not a terminal" error. I've also tried "ssh -t -t" but to no avail. But if I call the checkAuthType function from outside of the while loop, it works fine. What is it about the while loop that changes the terminal and how do I fix it? Thank you one thousand times in advance.
Another option to try to get around the problem would be to redirect the file to a different file descriptor and force read to read from it instead.
while read inputline <&3
do
ARRAY=(`echo $inputline | tr ',' ' '`)
HOSTNAME=${ARRAY[0]}
OS_TYPE=${ARRAY[1]}
checkAuthType $HOSTNAME $OS_TYPE
<more irrelevant code>
done 3< configfile.csv
I am guessing you are testing with linux. You should try add the -n flag to your (linux) ssh command to avoid having ssh read from stdin - as it normally reads from stdin the while loop is feeding it your csv.
UPDATE
You should (usually) use the -n flag when scripting with SSH, and the flag is typically needed for 'expected behavior' when using a while read-loop. It does not seem to be the main issue here, though.
There are probably other solutions to this, but you could try adding another -t flag to force pseudo-tty allocation when stdin is not a terminal:
ssh -n -t -t
BroSlow's approach with a different file descriptor seems to work! Since the read command reads from fd 3 and not stdin,
ssh and hence sudo still have or get a tty/pty as stdin.
# simple test case
while read line <&3; do
sudo -k
echo "$line"
ssh -t localhost 'sudo ls -ld /'
done 3<&- 3< <(echo 1; sleep 3; echo 2; sleep 3)

Using fifos and links to control remote process from a webpage (Linux)

I'm using mpg123 in a linux server and I'm trying to control it through a webpage (apache), using links to send different controls.
mpg123 has the -C flag so you can send characters to it. "s" key = start/stop, "f" key = next track... and so on.
I think I can send mpg123 those keys with a fifo, changing mpg123 stdin to the fifo stdout but i don't know how to use the fifo in this case (how to make mpg123 "listen" to another stdin).
What I've done is:
mkfifo myfifo
myfifo | mpg123 -C -# musiclist.txt
And then I've created keys.txt adding some keys to the file:
echo "f" >> keys.txt
echo "s" >> keys.txt
Then:
cat keys.txt >> myfifo.fifo
This does not work.
Can someone explain ow can I use fifos to pass messages to a running mpg123?
I've googled it but can't find what I want.
This question seems to give me some light, but I still don't know how to make mpg123 listen to the fifo's output.
Thank you in advance,
What are you using to pipe myfifo?
I'll assume cat myfifo | mpg123 -C -# musiclist.txt
cat will close after the first file piped through myfifo. Try using tail -f myfifo | ... instead to keep it open after EOF.
mkfifo myfifo
tail -f myfifo | mpg123 .. &
# send commands
echo .. > myfifo
sleep 5
echo .. > myfifo
tail is optional unless mpg123 exits if it receives EOF on stdin. Otherwise you could use: <myfifo mpg123 ...
& at the end (control operator to execute the command in the background) is optional if you run echo commands in another terminal.
mpg123 has it's own --fifo option

using sed and pstree to display the type of terminal being used

I've been trying to display the type of terminal being used as the name only. For instance if I was using konsole it would display konsole. So far I've been using this command.
pstree -A -s $$
That outputs this.
systemd---konsole---bash---pstree
I have the following that can extract konsole from that line
pstree -A -s $$ | sed 's/systemd---//g;s/---.*//g' | head -1
and that outputs konsole properly. But some people have output from just the pstree command that can look like this.
systemd---kdeinit4---terminator---bash---pstree
or this
systemd---kdeinit4---lxterminal---bash---pstree
and then when I add the sed command it extracts kdeinit4 instead of terminator. I can think of a couple scenarios to extract the type of terminal but none that don't contain conditional statements to check for specific types of terminals. The problem I'm having is I can't accurately predict how many non or non-relative things may be infront or behind of the terminal name or what they will be nor can I accurately predict what the terminal name will be. Does anyone have any ideas on a solution to this?
You could use
ps -p "$PPID" -o comm=
Or
ps -p "$PPID" -o fname=
If your shell does not have PPID variable set you could get it with
ps -p "$(ps -p "$$" -o ppid= | sed 's|\s\+||')" -o fname=
Another theory is that the parent process of the current shell that doesn't belong to the same tty as the shell could actually be the one that produces the virtual terminal, so we could find it like this as well:
#!/bin/bash
shopt -s extglob
SHELLTTY=$(exec ps -p "$$" -o tty=)
P=$$
while read P < <(exec ps -p "$P" -o ppid=) && [[ $P == +([[:digit:]]) ]]; do
if read T < <(exec ps -p "$P" -o tty=) && [[ $T != "$SHELLTTY" ]]; then
ps -p "$P" -o comm=
break
fi
done
I don't know how to isolate the terminal name on your system, but as a parsing exercise, and assuming the terminal is directly running your bash you could pipe the pstree output through:
awk -F"---bash---" ' NF == 2 { count = split( $1, arr, "---" ); print arr [count]; }'
This will find the word prior to the "---bash---" which in your examples is
konsole
terminator
lxterminal
If you want different shell types, you could expand the field separator to include them like:
awk -F"---(bash|csh)---" ' NF == 2 { count = split( $1, arr, "---" ); print arr[count]; }'
Considering an imaginary line like:
systemd---imaginary---monkey---csh---pstree
the awk would find "monkey" as the terminal name as well as anything from your test set.
No guarantees here, but I think this will work most of the time, on linux:
ps -ocomm= $(lsof -tl /proc/$$/fd/0 | grep -Fxf <(lsof -t /dev/ptmx))
A little explanation is probably in order, but see man ps, man lsof and (especially) man pts for information.
/dev/ptmx is a pseudo-tty master (on modern linux systems, and some other unix(-like) systems). A program will have one of these open if it is a terminal emulator, a telnet/ssh daemon, or some other program which needs a captive terminal (screen, for example). The emulator writes to the pseudo-tty master what it wants to "type", and reads the result from the pseudo-tty slave.
/proc/$$/fd/0 is stdin of process $$ (i.e. the shell in which the command is executed). If stdin has not been redirected, this will be a symlink to some slave pseudotty, /dev/pts/#. That is the other side of the /dev/ptmx device, and consequently all of the programs listed above which have /dev/ptmx open will also have some /dev/pts/# slave open as well. (You might think that you could use /dev/stdin or /dev/fd/0 instead of /proc/$$/fd/0, but those would be opened by lsof itself, and consequently would be its stdin; because of the way lsof is implemented, that won't work.) The -l option to lsof causes it to follow symlinks, so that will cause it to show the process which have the same pts open as the current shell.
The -t option to lsof causes it to produce "terse" output, consisting only of pids, one per line. The -Fx options to grep cause it to match strings, rather than regex, and to force a full line match; the -f FILE option causes it to accept the strings to match from FILE (which in this case is a process substitution), one per line.
Finally, ps -ocomm= prints out the "command" (chopped, by default, to 8 characters) corresponding to a pid.
In short, the command finds a list of terminal emulators and other master similar programs which have a master pseudo-tty, and a list of processes which use the pseudo-tty slave; finds the intersection between the two, and then looks up the command name for whatever results.
curTerm=$(update-alternatives --query x-terminal-emulator | grep '^Best:')
curTerm=${curTerm##*/}
printf "%s\n" "$curTerm"
And the result is
terminator
Of course it can be different.
Now you can use $curTerm variable in your sed command.
But I am not sure if this is going to work properly with symlinks.

Resources