How to split given text into 3 variables in bash and send to host at port? - linux

I want to write a command that listens to some port (say port 22222), receives a single line of text, and splits that line by spaces into port, host, and text by spaces. The text can have spaces in it too. So, for example, 1234 localhost blah de blah would be be split into 1234 for the port, localhost for the host, and blah de blah for the text. If the port is 0, the program exits. Otherwise the program sends the value of text to the host at the port and loops back to listening.
So I have in the terminal:
nc -k -l localhost 22222|some code goes here I think
and
echo 2016 localhost blah blah|nc localhost 22222
will cause blah blah to be sent to localhost at port 2016
and
echo 0 localhost blah blah|nc localhost 22222
will cause the program to exit
My question is what exactly goes into the "some code goes here I think" section?

Upon receive nc will echo the data to stdout, so you can process it as follows:
nc -k -l localhost 22222 | while read line
do
# "$line" contains the received text, do whatever you need with it
...
done

Since you are piping the output of netcat (nc) into "some code goes here I think", "some code goes here I think" needs to be a program or script that reads standard input and does what you want with that data.
Using pipes on the command line aren't the only way or getting the output of netcat and doing something with it. Since you mentioned you are using bash, probably the simplest thing to do would be to take the output on nc and then store that in a variable, then you can use another program like cut or awk to split the string up:
raw=`nc -k -l localhost 22222`
part1=`echo $raw | cut -f 1`
part2=`echo $raw | cut -f 2`
part3=`echo $raw | cut -f 3-`
Which should get you the parts you want stored in bash environment variables, which you can do what you like with later (e.g., exit if $part1=0).
Note that those are backticks in my example, not quotes. Backticks in bash take the result of the command inside them and return it as a string.

Related

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

Can I send a message to multiple hosts in one command using nc (netcat)?

Is it possible to do it in one netcat invocation?
This works:
nc WHKWDCTGABUZUN1 12345 -w 5
How do I make this work?
nc WHKWDCTGABUZUN1,WHKWDCTGABUZUN2,WHKWDCTGABUZUN3 12345 -w 5
As far as I know, nc cannot directly do what you want. But, as the man pages say, nc works nicely in scripts, so you can do something like:
#!/bin/bash
ADDRESSES=("WHKWDCTGABUZUN1" "WHKWDCTGABUZUN2" "WHKWDCTGABUZUN3")
for ADDR in ${ADDRESSES[#]}
do
nc "$ADDR" 12345 -w 5
done
You can wrap this into a shell script that will send whatever you pass on stdin to each of the hosts.
If this doesn't work for you, check out one or more of the beefed-up versions of nc, including ncat and socat, both of which are available for Linux. I'm not sure that they can do what you want either, but it's more likely.
You can't actually do that in a single line, the way you're asking. However, something like this may work:
printf "WHKWDCTGABUZUN1\nWHKWDCTGABUZUN2\nWHKWDCTGABUZUN3\n" |
while read address; do
nc "$address" 80 -w 5 <<< GET;
done

Shell script to find out if a port is being listened to using netstat?

I have a server where a certain port (9999) is being listened to by a PHP socket server. What happens is that devices can connect to the socket and send messages. The code works fine right now, however, I noticed that the socket would sometimes close or die off, and I need to be able to put it back up online automatically without me having to log in and run it again.
What I'm thinking of is writing a Shell script that would check via netstat if there's a process running on port 9999, and if there's none, the script would trigger the PHP socket server to go online again. This Shell script would then be called by Cron every 1 or 2 minutes to check if the PHP socket is running.
I have bare minimum knowledge about Shell scripting, and so far, this was the only other thing I wrote in Shell:
#!/bin/sh
if pidof "my process name here" >/dev/null; then
echo "Process already running"
else
echo "Process NOT running!"
sh /fasterthancron.sh
fi
I think I should be able to reuse this code to some degree but I'm not sure what to replace the if condition with.
I have the idea that I'm supposed to use netstat -tulpn to figure out what processes are running, but I'm not sure how to filter through that list to find if a specific process is running on port 9999.
If you use netstat -tlpn (or its replacement ss -tpln), you can grep for 9999 and look for processes listening on it under "Local Address".
ss -tpln | awk '{ print $4 }' | grep ':9999'
Alternatively, if you can, use netcat or telnet instead e.g. nc -v localhost 9999.
if echo -n "\cD" | telnet ${host} ${port} 2>/dev/null; then
...
fi
I wrote something similar a while back: docker-wait
This was forked from aanand's docker-wait
You can use famous netstat -tupln with a simple if/else logic to do this.
if [ -z "$(sudo netstat -tupln | grep 9999)" ];
then
echo notinuse;
else
echo inuse;
fi

Output a linux command to a url/port or scocket instead of writing it to a file

I have a command which out outputs certain data which i store in a ext file using a '>>' command.Now Instead of doing that I want to have a socket or a port on any server which will catch the output of the command.Basically i want to output all my script data to a socket or url which ever is possible.
Any help in this direction is most welcomed.
You can use socat to listening on a port 12345 and echo any data sent to it like this:
socat -u TCP-LISTEN:12345,keepalive,reuseaddr,fork STDOUT
If you want to capture it to a file as well (file.log), you can use the same command with tee:
socat -u TCP-LISTEN:12345,keepalive,reuseaddr,fork STDOUT | tee file.log
You can run your program to output to bash's TCP virtual device:
./prog > /dev/tcp/localhost/12345
If you don't want to use bash magic then you can also use socat to send the data:
./prog | socat - TCP-CONNECT:localhost:12345
The above example assume you are running your program and "logger" on the same system but you can replace "localhost" with the hostname or address of the system you wish to send to (where the socat is listening).

How to delay pipe netcat to connect on first input

Running in bash under Ubuntu:
I have a source that generates me some output, but not straight away. Let's assume it is a first netcat listening on a socket: netcat -l 12345.
And I would like to pipe it to an outgoing netcat (connecting over TCP), e.g. netcat -l 12345 | netcat localhost 54321. But the tricky bit is, that I know there is nothing listening for that incoming connection on localhost 54321 when I run the command, but I know there will be one when the first actual character arrives through the pipe.
So my question is: is there a way either:
to delay the execution of the outgoing netcat until the first character arrives into the pipe, or
to delay the outgoing netcat from trying to establish the TCP connection until it receives the first character on its standard input? (no straight option for that in man, switching to UDP is not acceptable)
Thanks in advance!
Edit: In reality, the source is more complex than a netcat, namely it is a listening netcat piped through all sort of stream modification.
Using the research you already did and that I commented to (by not knowing it was an answer to your own question), here is the full delayed_netcat.sh:
#!/bin/bash
read line
netcat "${#}" < <(echo $line ; cat)
This first waits for a line of input and later prepends that line using a simple echo to the "newly generated" input to the actual netcat. The rest of stdin is just redirected using cat which slurps it from stdin and adds it to the input of netcat. It also supports passing commandline options and arguments to the "real" netcat.
The usage is as follows:
netcat -l 12345 | cmd1 | cmd2 | ... | ./delayed_netcat.sh localhost 54321
The netcat is delayed till the first line is read. If you really want to start it after the first character is read the parts with read and echo need some rewrite.
Port Forwarding or Port Mapping with netcat:
ncat -l -p 12345 -c 'ncat localhost 54321'
Using socat:
socat TCP4-LISTEN:12345 TCP4:localhost:54321
This command exits after the first connection is done.
I have found an answer to my question, but it is awful... so still looking for something better.
netcat -l 12345 | gawk '(NR==1){print""}{print;fflush()}' | ./delayed_netcat.sh
where ./delayed_netcat.sh:
#!/bin/sh
read line
netcat localhost 12345
So the read line delays the netcat localhost 12345 by waiting for and consuming the first input line, and I use gawk '(NR==1){print""}{print;fflush()}' to insert an empty line just before the first record... I'm sure there is room for much improvement to that!

Resources