Andy_m4
Well-Known Member
Das Web ist allgegenwärtig. :-)
Und natürlich kann man die Technik auch für eigene Zwecke nutzen. Beispielsweise für eine Website, die einem Systeminformationen (oder dergleichen) anzeigt.
Um sich deshalb aber nicht einen vollständigen Webserver (inkl. CGI etc.) aufzuhalsen, bauen wir uns den Webserver mit ein bisschen Shell-Skript + netcat selbst:
Der Webserver ignoriert alles was er vom Client (Browser) bekommt und gibt stumpf die Ausgabe des ihm übergebenen Shell-Skriptes zurück. Unter der Annahme das man das Webserver-Skript unter dem Namen serve-script-via-http.sh gespeichert hat, kann es also so aufrufen:
Damit läuft der Webserver auf
Wir wollen aber natürlich lieber eine schicke HTML-Ausgabe. Also lassen wir es so und schreiben uns dann noch ein entsprechendes Status-Ausgabe-Skript (status-as-html.sh):
Ich glaube/hoffe, das meiste ist selbsterklärend. :-)
Die Skripte sind POSIX-Shell benutzen nur Tools aus dem FreeBSD-Base-System und sollten daher ohne weitere Packages/Ports laufen.
Theoretisch kann man sie direkt verwenden, aber in erster Linie dienen die der Veranschaulichung wie man so etwas machen kann.
Ein paar Hinweise noch:
Und natürlich kann man die Technik auch für eigene Zwecke nutzen. Beispielsweise für eine Website, die einem Systeminformationen (oder dergleichen) anzeigt.
Um sich deshalb aber nicht einen vollständigen Webserver (inkl. CGI etc.) aufzuhalsen, bauen wir uns den Webserver mit ein bisschen Shell-Skript + netcat selbst:
Bash:
#!/bin/sh
if [ $# -lt 2 ]; then
echo "Usage: $0 <script> <port> [<bindaddress>]"
echo " <script>: Path to the script that generates the HTML output"
echo " <port>: Port number to listen on"
echo " <bindaddress>: Address to listen on (for Example: localhost)"
exit 1
fi
SCRIPT=$1
PORT=$2
BINDADDR=${3:-}
echo "Status: http://${BINDADDR:-$(hostname)}:$PORT"
while true; do
{
now="$(env LANG=C date +'%a, %d %b %Y %H:%M:%S %Z')"
echo "HTTP/1.1 200 OK"
echo "Content-Type: text/html; charset=utf-8"
echo "Cache-Control: max-age=5"
echo "X-Robots-Tag: noarchive"
echo "Date: $now"
echo "Last-Modified: $now"
echo "Expires: $(env LANG=C date -v+1M +'%a, %d %b %Y %H:%M:%S %Z')"
echo "Connection: close"
echo ""
sh "$SCRIPT"
} | nc -l ${BINDADDR:+$BINDADDR} "$PORT" -w 1 > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: nc exited with code $?"
exit 5
fi
done
sh server-script-via-http.sh status-as-html.sh 8080 localhost
Damit läuft der Webserver auf
http://localhost:8080
und piped die Ausgabe von status-as-html.sh via TCP/IP zum Webbrowser. Im Prinzip reicht es, wenn das Status-Skript einfach stumpf Text via echo ausgibt. Wenns plain text sein soll, muss man den Content-Type in Zeile 20 auf text/plain setzen, damit der Browser das vernünftig anzeigt.Wir wollen aber natürlich lieber eine schicke HTML-Ausgabe. Also lassen wir es so und schreiben uns dann noch ein entsprechendes Status-Ausgabe-Skript (status-as-html.sh):
Bash:
#!/bin/sh
SERVERS="fritz.box mynas www.freebsd.org "
IFS=' '
check_server() {
server=$1
ping -c 1 -W 1 "$server" > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "<li>$server: <span class=\"online\">reachable</span></li>"
else
echo "<li>$server: <span class=\"offline\">not reachable</span></li>"
fi
}
# Funktion: make_number_human_readable
# Beschreibung: Konvertiert eine Zahl in eine lesbare Form mit Einheiten (B, K, M, G, T)
# Parameter: $1 - die Zahl, die konvertiert werden soll
make_number_human_readable() {
local num=$1
local unit="B"
if [ $num -gt 1024 ]; then
num=$(($num / 1024))
unit="K"
fi
if [ $num -gt 1024 ]; then
num=$(($num / 1024))
unit="M"
fi
if [ $num -gt 1024 ]; then
num=$(($num / 1024))
unit="G"
fi
if [ $num -gt 1024 ]; then
num=$(($num / 1024))
unit="T"
fi
echo "${num} ${unit}"
}
# make-table-line Cell1 Cell2 Cell3 ...
# wird zu:
# <tr><td>Cell1</td><td>Cell2</td><td>Cell3</td> ... </tr>
make-table-line() {
echo "<tr>"
for param in "$@"; do
echo "<td>$param</td>"
done
echo "</tr>"
}
# Funktion: show-status
# Beschreibung: Zeigt einen Status an, optional mit einem benutzerdefinierten HTML-Tag
# Parameter:
# $1: Header-Text
# $2: Status-Text
# $3: Optionaler HTML-Tag (Default: keiner)
show-status() {
local header="$1"
local state="$2"
local tag="$3"
echo "<h2>$header</h2>"
echo "<p>"
if [ -n "$tag" ]; then
echo "<$tag>"
echo "$state"
echo "</$tag>"
else
echo "$state"
fi
echo "</p>"
}
echo "<!DOCTYPE html> <html>
<head>
<meta http-equiv=\"refresh\" content=\"65\" >
<title>Server Status</title>
<style>
h1 { font-size: 1.2em; font-weight:bolder;}
h2 { font-size: 1.1em; font-weight:bolder;}
span.online { color: green;}
span.offline { color: red;}
table {
border-collapse: collapse;
margin: 20px;
}
tr {
border-bottom: 1px solid #ccc;
}
td {
padding: 10px;
border: 1px dotted #666;
}
.line {
display: flex;
flex-wrap: wrap;
}
.data {
}
.label {
margin-right: 0.8em;
margin-left: 0.8em;
}
.decoration {
color: #666;
}
.data[data-tag=\"special\"] {
color: #980081;
}
.data[data-tag=\"node\"] {
color: #000BFE;
}
.data[data-tag=\"fstype\"] {
color: #980017;
}
.data[data-tag=\"opts\"] {
color: #333;
}
</style>
</head>
<body>"
echo "<a name='anfang'>"
# --------------------------------------------
echo "<h1>Systeminfo zu $(hostname)</h1>"
echo "<p>"
echo "<table>"
if [ $(id -u) -eq 0 ]; then # root?
freebsd-update updatesready
if [ $? -ne 2 ]; then
make-table-line "FreeBSD-Update: " "Ready for install"
fi
fi
make-table-line "Systemzeit:" "$(date)"
make-table-line "Uptime:" "$(uptime)"
make-table-line "System:" "$(uname -s) $(freebsd-version)"
make-table-line "RAM gesamt:" "$(make_number_human_readable $(sysctl -n hw.physmem))"
make-table-line "Swap gesamt:" "$(make_number_human_readable $(sysctl -n vm.swap_total))"
make-table-line "RAM frei:" "$(make_number_human_readable $(expr $(sysctl -n vm.v_free_target) \* $(sysctl -n hw.pagesize) ))"
echo "</table>"
echo "</p>"
show-status "Recent Systemmessages" "$(tail -n 5 /var/log/messages)" "pre"
show-status "ZPools" "$(zpool list)" "pre"
show-status "ZFS-Datasets" "$(zfs list)" "pre"
show-status "Mounts" "$(mount --libxo html | sort)"
show-status "Jails" "$(jls)" "pre"
# --------------------------------------------
echo "<h1>Servers reachability</h1>"
echo "<ul>"
for server in $SERVERS; do
echo "$(check_server $server)"
done
echo "</ul>"
# --------------------------------------------
echo "<p> </p>"
echo "<p style='text-align: right;'><a href='#anfang'>hoch</a> </p>"
echo "</body></html>"
Die Skripte sind POSIX-Shell benutzen nur Tools aus dem FreeBSD-Base-System und sollten daher ohne weitere Packages/Ports laufen.
Theoretisch kann man sie direkt verwenden, aber in erster Linie dienen die der Veranschaulichung wie man so etwas machen kann.
Ein paar Hinweise noch:
- der "Webserver" hat kein Verschlüsselung/SSL oder so. Es ist http-only. Möglicherweise zickt deshalb der Browser
- man muss aufpassen bei Befehle die Seiteneffekte haben oder eine lange Laufzeit
- man muss sich darüber im klaren sein, das der Webserver von "außen" (zumindest LAN) erreichbar ist, wenn man das localhost im Aufruf weglässt (was auch ein Security-Problem ist, je nachdem welche Informationen man rausgibt)
- es wird erst die Seite erzeugt und dann netcat aufgerufen. Das kann dazu führen, das die Seite nicht aktuell ist. Das ist sie dann erst beim Reload. In soll der entsprechende Meta-Tag in status-as-html.sh in Zeile 82 dafür sorgen, das der Browser die Seite nach jeweils 65 Sekunden neu lädt (sozusagen Self-Refresh), so das man immer (halbwegs) aktuelle Werte hat, wenn man die Page ständig im Browser offen hat.