How to Pipe Command Output (uptime/df) to cURL as POST Data: A Linux Sysadmin’s Guide


3 views

When I first tried sending command output through cURL, I ran into the same issue many Linux admins face. The naive approach:

uptime | curl http://monitoring.example.com/api -T -

fails because -T/--upload-file expects a file, not stdin data. This is a common misconception when starting with cURL.

For sending command output as POST data, we need to properly format the request. Here are three reliable methods:

# Method 1: Using --data-binary
uptime | curl -X POST http://monitoring.example.com/api --data-binary @-

# Method 2: Capturing output first
SERVER_STATS=$(uptime && df -h)
curl -X POST -d "$SERVER_STATS" http://monitoring.example.com/api

# Method 3: For JSON APIs
curl -X POST -H "Content-Type: application/json" \
-d "{\"uptime\":\"$(uptime)\",\"disk\":\"$(df -h)\"}" \
http://monitoring.example.com/api

Here's how I monitor multiple servers in our production environment:

#!/bin/bash
ENDPOINT="https://monitoring.example.com/api/v1/telemetry"
AUTH_TOKEN="Bearer xxxxxxxx"

# Collect system metrics
METRICS=$(cat <1 {print $1,$3,$4,$5}' | jq -R -s -c 'split("\n")[:-1] | map(split(" "))')
}
EOF
)

# Send with cURL
curl -X POST "$ENDPOINT" \
  -H "Authorization: $AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$METRICS"

When dealing with complex output that might contain special characters, use proper escaping:

curl -X POST http://example.com/api \
  --data-urlencode "uptime=$(uptime)" \
  --data-urlencode "disk=$(df -h)"

While cURL is the gold standard, here are alternatives:

# Using wget
uptime | wget --post-data=- http://example.com/api

# Using netcat (for debugging)
uptime | nc monitoring.example.com 80

Remember that wget lacks some of cURL's advanced HTTP features, while netcat should only be used for testing.


When trying to send command output via cURL, many developers first attempt:

uptime | curl http://example.com -T -

This approach fails because -T is for file uploads (PUT requests), not POST data. The server won't receive your command output as expected.

To correctly send command output as POST data, use one of these methods:

# Method 1: Simple POST
uptime | curl -X POST --data-binary @- http://example.com

# Method 2: With content-type
df -h | curl -X POST -H "Content-Type: text/plain" --data-binary @- http://example.com/api

For sending multiple command outputs in JSON format:

curl -X POST -H "Content-Type: application/json" -d \
'{
  "uptime": "'"$(uptime)"'",
  "disk": "'"$(df -h)"'"
}' \
https://example.com/api/monitoring

If your endpoint expects form-urlencoded data:

curl -X POST --data-urlencode "uptime=$(uptime)" \
--data-urlencode "disk=$(df -h)" \
https://example.com/api/status

For more complex scenarios with multiple data sources:

curl -X POST -F "uptime=<-" -F "disk=<-" http://example.com \
<<< "Uptime: $(uptime)
Disk:
$(df -h)"

Always include error handling when scripting:

if ! output=$(df -h 2>&1); then
  echo "Disk check failed" >&2
  exit 1
fi

if ! curl -X POST -H "Content-Type: text/plain" \
--data-binary "$output" \
http://example.com/disk-stats; then
  echo "Failed to send data" >&2
  exit 1
fi

When sending sensitive data:

# Use HTTPS
curl --tlsv1.3 https://secure.example.com/api \
-H "Authorization: Bearer $API_KEY" \
--data-urlencode "stats=$(df -h)"