5

I want to let netcat on my server execute a script that works on a file that has just been sent and have the output of this script be sent as the response to the client. My approach is:

On the receiving site:

nc.traditional -l -p 2030 -e "./execute.sh" > file.iso

On the sending site:

cat file.iso - | nc.traditional -w 1 serverAddress 2030

Right now, the receiving site executes the script before the file has been transferred completely, but sends the output of the script back to the sending site and then closes the connection. I'd like the receiving site to wait until the file has been completely transferred before executing the script.

4

You need some way for the receiving end to recognize the end of the transferred file. With cat file - | nc in the sending side, the data stream through the pipe will make no separation between the contents of the file, and whatever the user types on the terminal (cat - reads the terminal). Also, by default, netcat doesn't react to an EOF on its input, but we can use -q to have it send the EOF along.

So, the receiving script could be something like this:

#!/bin/bash
filename=$1
cat > "$filename"

hash=$(shasum "$filename" |sed -e 's/ .*//')
printf "received file \"%s\" with SHA-1 hash %s\n" "$filename" "$hash"

The cat reads the input until EOF, saving the file. Whatever follows, is executed after the file is received. Here, the script sends back the SHA-256 hash of the data it received.

Then, on the receiving side, run:

$ nc.traditional -l -p 12345 -c "./receivefile.sh somefilename"

and on the sending side:

$ cat sourcefile | nc.traditional -q 9999 localhost 12345
received file "somefilename" with SHA-1 hash 3e8a7989ab68c8ae4a9cb0d64de6b8e37a7a42e5

The script above takes the file name as an argument, so I used -c instead of -e, but of course you can also redirect the output of nc to the destination file, as you did in the question.


If you want to send the filename from the sending side too, you could do something like this on the receiving side:

#!/bin/bash
read -r filename
[[ $filename = */* ]] && exit 1       # exit if the filename contains slashes
cat > "$filename"
echo "received $filename"

and then send with (echo filename; cat filename) | nc -q 9999 localhost 12345. (You may want to be way more careful with the remote-supplied filename, here. Or just use something designed for file transfer, like scp.)

Instead of using nc, you could do this similarly with SSH:

cat filename | ssh user@somehost receive.sh

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.