Implementing netcat in bash
Asked Answered
S

3

5

As the basis for a larger script I'm trying to write I'm trying to basically implement a basic netcat client in bash. My current script techincally works, it looks like this:

#!/bin/bash

exec 3<>/dev/tcp/$1/$2         

cat <&3 &                      
cat <&1 >3

The problem with it is that it leaves a hanging cat process which needs to be killed, but I can't figure an automatic way to do so, and manually running pkill cat doesn't really seem sporting.

Sicular answered 24/8, 2012 at 23:53 Comment(0)
D
4

It is a horrid kludge, but you could spawn a subshell and so something like this:

CAT1_PID=$$
echo CAT1_PID > /tmp/CAT1_PID
exec cat <&3 &

Then, of course, you run into race conditions if more than one copy of this script happens to be running.

Depending on your shell, you may be able to call some form of exec and "rename" cat in the PS list. Then you can

pkill the_cat_that_ate_the_network
Discountenance answered 25/8, 2012 at 0:1 Comment(2)
Do you know of a way to automatically call pkill when I control-c my script?Sicular
I haven't done any real scripting in quite a while, so I have to rely on the almighty Google. If you are using bash then you can try this. Bash Trap I've found a bunch of different shell variants as the default shell lately, so be sure that you have your #! pointed to the right place.Discountenance
S
7

I've accepted Jeremy's answer as correct, but for anyone curious here's the full script I ended up with:

#!/bin/bash

exec 3<>/dev/tcp/$1/$2         

control_c()
{
    kill $CAT_PID
    exit $?
}

trap control_c SIGINT

cat <&3 &                      
CAT_PID=$!
cat >&3
Sicular answered 27/8, 2012 at 19:21 Comment(3)
Upvote for posting your working solution. It is great when people do that!Discountenance
Thanks for this! I've done pretty much the same, but using pkill -P $$ instead of catching the PID, and an additional pkill -P $$ at the end to catch connections closed by the client (which resulted in a disowned cat hanging around for a short while)Ribal
add a "wait" at the end to prevent the script from existing until the remote end has sent its response. Otherwise the cat gets abandoned as soon as stdin is closed.Likable
D
4

It is a horrid kludge, but you could spawn a subshell and so something like this:

CAT1_PID=$$
echo CAT1_PID > /tmp/CAT1_PID
exec cat <&3 &

Then, of course, you run into race conditions if more than one copy of this script happens to be running.

Depending on your shell, you may be able to call some form of exec and "rename" cat in the PS list. Then you can

pkill the_cat_that_ate_the_network
Discountenance answered 25/8, 2012 at 0:1 Comment(2)
Do you know of a way to automatically call pkill when I control-c my script?Sicular
I haven't done any real scripting in quite a while, so I have to rely on the almighty Google. If you are using bash then you can try this. Bash Trap I've found a bunch of different shell variants as the default shell lately, so be sure that you have your #! pointed to the right place.Discountenance
P
0

Just a matter of followup…

whois() {
        (
                exec 3<>/dev/tcp/whois.ripe.net/43
                echo "$*" >&3
                cat <&3
        )
}

Just in case you have a really simple protocol (like WHOIS).

Pedagogue answered 24/11, 2023 at 16:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.