Networking#

Bash itself doesn’t speak the network, it orchestrates programs that do. The toolkit is mostly coreutils plus a handful of well-known network utilities.

HTTP#

$ curl -fsSL https://example.com/
$ curl -I https://example.com/
$ curl -X POST -H 'content-type: application/json' \
     -d '{"a":1}' https://api.example.com/v1/items
$ curl -fsS --retry 3 --retry-connrefused -o file.tgz \
     https://example.com/file.tgz

$ wget -q -O- https://example.com/
$ wget -nc https://example.com/file.tgz

Common flags worth memorizing:

  • -f (curl), fail on HTTP errors. Use everywhere; without it scripts silently miss 4xx/5xx.

  • -s, silent. Often paired with -S to keep error messages.

  • -L, follow redirects.

  • --max-time, --connect-timeout, always set both in scripts.

JSON#

$ curl -fsS https://api.example.com/users/1 | jq '.name'
$ jq -r '.items[].id' input.json
$ curl -fsS -X POST https://api.example.com/items \
     --data-raw "$(jq -n --arg n "$NAME" '{name:$n}')"

TCP / UDP#

Bash has built-in /dev/tcp and /dev/udp pseudo-paths, handy for probes when nc isn’t available:

$ if (echo > /dev/tcp/host/22) 2>/dev/null; then
  $ echo "open"
$ fi

$ exec 3<>/dev/tcp/example.com/80
$ printf 'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n' >&3
$ cat <&3
$ exec 3<&-

For real interactive work, use netcat:

$ nc -zv host 22
$ nc -u -zv host 53
$ nc -l -p 4444

DNS#

$ getent hosts example.com
$ dig +short example.com
$ dig +short example.com AAAA
$ dig @8.8.8.8 example.com
$ host example.com

SSH and File Transfer#

$ ssh user@host 'systemctl status nginx'
$ scp file user@host:/path/
$ rsync -aP src/ user@host:/path/
$ rsync -aP --delete src/ user@host:/path/

Authentication Tokens#

Don’t put tokens on the command line; they leak through ps, history, and logs.

$ curl -H "Authorization: Bearer $(cat ~/.config/myapp/token)" ...
$ curl -H "Authorization: Bearer $TOKEN" ...
$ curl --netrc-file ~/.netrc ...

Diagnostics#

$ ping -c 3 host
$ traceroute host
$ mtr host
$ ss -tulpn
$ tcpdump -ni any port 443
$ tshark -i any -f 'port 443'

For “is this URL up and what does it look like”:

$ curl -o /dev/null -s -w 'http=%{http_code} time=%{time_total}\n' https://example.com/