patchcenter/app/scripts/server_audit.sh
Khalid MOUTAOUAKIL 20cd9c7d80 Audit complet: import JSON, carte flux, carte applicative
- server_audit_full_service.py: SSH PSMP/cle, parsing, stockage JSONB, flow map
- server_audit.sh: script bash avec sudo (compatible PSMP cybsecope)
- audit_full router: import JSON, liste, detail, carte flux
- Templates: liste audits, detail 8 onglets, carte flux + carte applicative
- Jointures: server_id via servers, dest_server via server_ips
- Sous-menu Audit > Complet dans la sidebar

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:06:55 +02:00

412 lines
18 KiB
Bash
Executable File

#!/bin/bash
# Audit complet serveur — applicatif + reseau + correlation
# Compatible RHEL 7/8/9
# Usage : bash server_audit.sh
HOSTNAME=$(hostname -s 2>/dev/null || hostname)
DATE=$(date '+%Y-%m-%d %H:%M:%S')
EXCLUDE_PROC="kworker|ksoftirq|migration|watchdog|kthread|rcu_|irq/|scsi|ata_|writeback|sshd:.*notty|bash /tmp|server_audit|capture_state|PM2.*God Daemon"
EXCLUDE_SVC="auditd|chronyd|crond|dbus|firewalld|getty|irqbalance|kdump|lvm2|lvmetad|NetworkManager|polkit|rsyslog|sshd|sssd|systemd|tuned|qualys|sentinelone|zabbix|commvault|veeam|tina|login|agetty|mingetty|logind|accounts-daemon|udisksd"
echo "########################################################"
echo "# AUDIT COMPLET — $HOSTNAME"
echo "# $DATE"
echo "# OS: $(cat /etc/redhat-release 2>/dev/null || head -1 /etc/os-release 2>/dev/null)"
echo "# Kernel: $(uname -r)"
echo "# Uptime: $(uptime -p 2>/dev/null || uptime)"
echo "########################################################"
##############################################################
# PARTIE 1 — APPLICATIF
##############################################################
echo ""
echo "========================================================"
echo " PARTIE 1 — ANALYSE APPLICATIVE"
echo "========================================================"
# ── 1.1 Services applicatifs running ──
echo ""
echo "=== 1.1 SERVICES APPLICATIFS RUNNING ==="
echo "SERVICE|ENABLED|MAIN_PID|USER|EXEC_START"
for svc in $(sudo systemctl list-units --type=service --state=running --no-pager --no-legend | awk '{print $1}'); do
svc_short=$(echo "$svc" | sed 's/.service//')
echo "$svc_short" | grep -qiE "$EXCLUDE_SVC" && continue
enabled=$(sudo systemctl is-enabled "$svc" 2>/dev/null)
pid=$(sudo systemctl show -p MainPID "$svc" 2>/dev/null | awk -F= '{print $2}')
user=$(sudo systemctl show -p User "$svc" 2>/dev/null | awk -F= '{print $2}')
execstart=""
[ -n "$pid" ] && [ "$pid" != "0" ] && [ -f "/proc/$pid/cmdline" ] && \
execstart=$(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null | cut -c1-150)
if [ -z "$execstart" ]; then
execstart=$(sudo systemctl show -p ExecStart "$svc" 2>/dev/null | grep -oP '(?<=path=)\S+' | head -1)
fi
echo "$svc_short|$enabled|$pid|${user:-root}|$execstart"
done
# ── 1.2 Processus applicatifs ──
echo ""
echo "=== 1.2 PROCESSUS APPLICATIFS ==="
echo "PID|PPID|USER|EXE|CWD|CMDLINE|RESTART_HINT"
for pid in $(sudo ls -d /proc/[0-9]* 2>/dev/null | sed 's|/proc/||' | sort -n); do
[ ! -f /proc/$pid/cmdline ] && continue
cmd=$(tr '\0' ' ' < /proc/$pid/cmdline 2>/dev/null)
[ -z "$cmd" ] && continue
echo "$cmd" | grep -qE '^\[' && continue
echo "$cmd" | grep -qiE "$EXCLUDE_PROC" && continue
user=$(sudo stat -c %U /proc/$pid 2>/dev/null)
ppid=$(sudo awk '/PPid/{print $2}' /proc/$pid/status 2>/dev/null)
exe=$(sudo readlink /proc/$pid/exe 2>/dev/null)
cwd=$(sudo readlink /proc/$pid/cwd 2>/dev/null)
is_interesting=0
[ "$ppid" = "1" ] && is_interesting=1
echo "$cwd" | grep -qi "/applis" && is_interesting=1
echo "$exe" | grep -qiE "node|java|python|ruby|perl|php|tomcat" && is_interesting=1
echo "$cmd" | grep -qiE "/applis|\.jar|\.js |\.py |\.rb " && is_interesting=1
sudo ss -tlnp 2>/dev/null | grep "pid=$pid," >/dev/null && is_interesting=1
[ "$is_interesting" = "0" ] && continue
echo "$cmd" | grep -qiE "$EXCLUDE_SVC" && continue
# Exclure workers enfants (meme exe que le parent)
if [ "$ppid" != "1" ] && [ -n "$exe" ]; then
parent_exe=$(sudo readlink /proc/$ppid/exe 2>/dev/null)
[ "$exe" = "$parent_exe" ] && continue
# Exclure enfants dont le grandparent est PM2 God Daemon
grandppid=$(sudo awk '/PPid/{print $2}' /proc/$ppid/status 2>/dev/null)
if [ -n "$grandppid" ]; then
grandp_cmd=$(tr '\0' ' ' < /proc/$grandppid/cmdline 2>/dev/null)
echo "$grandp_cmd" | grep -qiE "PM2.*God Daemon" && continue
fi
fi
# Construire hint de redemarrage
hint=""
# Priorite 1: systemd
svc_match=$(sudo systemctl status $pid 2>/dev/null | head -1 | grep -oP '\S+\.service' | head -1)
if [ -z "$svc_match" ]; then
exe_name=$(basename "$exe" 2>/dev/null)
[ -n "$exe_name" ] && svc_match=$(sudo systemctl list-units --type=service --state=running --no-pager --no-legend 2>/dev/null | grep -i "$exe_name" | awk '{print $1}' | head -1)
fi
if [ -n "$svc_match" ]; then
hint="sudo systemctl restart $svc_match"
# Priorite 2: PM2
elif command -v pm2 &>/dev/null; then
pm2_name=""
pm2_json=""
for pm2_user in "$user" root $(sudo ps aux 2>/dev/null | grep -i 'PM2\|pm2' | grep -v grep | awk '{print $1}' | sort -u); do
pm2_json=$(su - "$pm2_user" -c "pm2 jlist 2>/dev/null" 2>/dev/null)
[ -z "$pm2_json" ] && continue
pm2_name=$(echo "$pm2_json" | grep -oP '"pid"\s*:\s*'$pid'\b[^}]*"name"\s*:\s*"\K[^"]+' 2>/dev/null | head -1)
[ -n "$pm2_name" ] && break
pm2_name=$(echo "$pm2_json" | grep -oP '"name"\s*:\s*"\K[^"]+(?=[^}]*"pid"\s*:\s*'$pid'\b)' 2>/dev/null | head -1)
[ -n "$pm2_name" ] && break
done
if [ -n "$pm2_name" ]; then
pm2_bin=$(which pm2 2>/dev/null || echo "/usr/local/bin/pm2")
pm2_exec=$(echo "$pm2_json" | grep -oP '"pm_exec_path"\s*:\s*"\K[^"]+' 2>/dev/null | head -1)
pm2_args=$(echo "$pm2_json" | grep -oP '"args"\s*:\s*\[\K[^\]]+' 2>/dev/null | head -1 | sed 's/"//g; s/,/ /g')
if [ -n "$pm2_exec" ] && [ -n "$pm2_args" ]; then
hint="su - $pm2_user -c '$pm2_bin start $pm2_exec --name $pm2_name -- $pm2_args'"
else
hint="su - $pm2_user -c '$pm2_bin restart $pm2_name'"
fi
fi
fi
# Priorite 3: start script dans cwd
if [ -z "$hint" ] && [ -n "$cwd" ] && [ -d "$cwd" ]; then
start_script=$(find "$cwd" -maxdepth 1 \( -name "start*" -o -name "run*" -o -name "*.sh" \) -executable 2>/dev/null | head -1)
if [ -n "$start_script" ]; then
hint="su - $user -c 'cd $cwd && $start_script'"
else
hint="su - $user -c 'cd $cwd && $(echo $cmd | cut -c1-120)'"
fi
fi
# Priorite 4: commande directe
if [ -z "$hint" ]; then
hint="su - $user -c '$(echo $cmd | cut -c1-120)'"
fi
echo "$pid|$ppid|$user|$exe|$cwd|$(echo $cmd | cut -c1-150)|$hint"
done
# ── 1.3 Services failed ──
echo ""
echo "=== 1.3 SERVICES EN ECHEC ==="
failed=$(sudo systemctl list-units --type=service --state=failed --no-pager --no-legend 2>/dev/null)
if [ -n "$failed" ]; then
echo "$failed"
else
echo "Aucun service en echec"
fi
# ── 1.4 Needs-restarting ──
echo ""
echo "=== 1.4 NEEDS-RESTARTING ==="
if ! command -v needs-restarting &>/dev/null; then
major=$(rpm -E %{rhel} 2>/dev/null || cat /etc/redhat-release 2>/dev/null | grep -oP '\d+' | head -1)
if [ "$major" -ge 9 ] 2>/dev/null; then
dnf install -y dnf-utils 2>&1 | tail -1
elif [ "$major" -ge 8 ] 2>/dev/null; then
dnf install -y yum-utils 2>&1 | tail -1
else
yum install -y yum-utils 2>&1 | tail -1
fi
fi
if command -v needs-restarting &>/dev/null; then
sudo needs-restarting -r 2>/dev/null
echo "EXIT_CODE=$?"
echo "--- Services a redemarrer ---"
sudo needs-restarting -s 2>/dev/null
else
echo "sudo needs-restarting non disponible"
fi
# ── 1.5 Espace disque ──
echo ""
echo "=== 1.5 ESPACE DISQUE ==="
df -h --output=target,size,used,avail,pcent 2>/dev/null | grep -vE '^(tmpfs|devtmpfs)' || df -h 2>/dev/null
##############################################################
# PARTIE 2 — RESEAU
##############################################################
echo ""
echo "========================================================"
echo " PARTIE 2 — ANALYSE RESEAU"
echo "========================================================"
# ── 2.1 Interfaces et IPs ──
echo ""
echo "=== 2.1 INTERFACES RESEAU ==="
echo "INTERFACE|IP|MASK|STATE|MAC"
ip -4 -o addr show 2>/dev/null | while read idx iface scope ip_mask rest; do
ip=$(echo "$ip_mask" | cut -d/ -f1)
mask=$(echo "$ip_mask" | cut -d/ -f2)
state=$(ip link show "$iface" 2>/dev/null | grep -oP '(?<=state )\S+' | head -1)
mac=$(ip link show "$iface" 2>/dev/null | grep -oP 'link/ether \K\S+' | head -1)
echo "$iface|$ip|/$mask|${state:-UP}|${mac:--}"
done
# ── 2.2 Routes ──
echo ""
echo "=== 2.2 TABLE DE ROUTAGE ==="
echo "DESTINATION|GATEWAY|INTERFACE|METRIC"
ip route show 2>/dev/null | while read line; do
dest=$(echo "$line" | awk '{print $1}')
gw=$(echo "$line" | grep -oP '(?<=via )\S+')
iface=$(echo "$line" | grep -oP '(?<=dev )\S+')
metric=$(echo "$line" | grep -oP '(?<=metric )\S+')
echo "$dest|${gw:-direct}|${iface:--}|${metric:--}"
done
# ── 2.3 Ports en ecoute ──
echo ""
echo "=== 2.3 PORTS EN ECOUTE ==="
echo "PROTO|ADDR:PORT|PID|PROCESS|USER|SERVICE"
sudo ss -tlnp 2>/dev/null | grep LISTEN | while read state recvq sendq local peer info; do
pid=$(echo "$info" | grep -oP 'pid=\K[0-9]+' | head -1)
proc=$(echo "$info" | grep -oP '"\K[^"]+' | head -1)
port=$(echo "$local" | grep -oP ':\K[0-9]+$')
user=""
[ -n "$pid" ] && user=$(sudo stat -c %U /proc/$pid 2>/dev/null)
svc=$(getent services "$port/tcp" 2>/dev/null | awk '{print $1}')
echo "TCP|$local|${pid:--}|${proc:--}|${user:--}|${svc:--}"
done
sudo ss -ulnp 2>/dev/null | grep -v 'State' | while read state recvq sendq local peer info; do
[ -z "$local" ] && continue
pid=$(echo "$info" | grep -oP 'pid=\K[0-9]+' | head -1)
proc=$(echo "$info" | grep -oP '"\K[^"]+' | head -1)
port=$(echo "$local" | grep -oP ':\K[0-9]+$')
user=""
[ -n "$pid" ] && user=$(sudo stat -c %U /proc/$pid 2>/dev/null)
svc=$(getent services "$port/udp" 2>/dev/null | awk '{print $1}')
echo "UDP|$local|${pid:--}|${proc:--}|${user:--}|${svc:--}"
done
# ── 2.4 Connexions etablies ──
echo ""
echo "=== 2.4 CONNEXIONS ETABLIES ==="
echo "DIRECTION|PROTO|LOCAL|REMOTE|PID|PROCESS|USER|STATE"
listen_ports=$(sudo ss -tlnp 2>/dev/null | grep LISTEN | grep -oP '\S+:(\d+)\s' | grep -oP ':\K\d+' | sort -u)
sudo ss -tnp 2>/dev/null | grep -v 'State' | while read state recvq sendq local remote info; do
[ "$state" = "State" ] && continue
[ -z "$local" ] && continue
pid=$(echo "$info" | grep -oP 'pid=\K[0-9]+' | head -1)
proc=$(echo "$info" | grep -oP '"\K[^"]+' | head -1)
user=""
[ -n "$pid" ] && user=$(sudo stat -c %U /proc/$pid 2>/dev/null)
local_port=$(echo "$local" | grep -oP ':\K[0-9]+$')
direction="OUT"
echo "$listen_ports" | grep -qx "$local_port" && direction="IN"
echo "$direction|TCP|$local|$remote|${pid:--}|${proc:--}|${user:--}|$state"
done
# ── 2.5 Resume flux entrants ──
echo ""
echo "=== 2.5 RESUME FLUX ENTRANTS (par port) ==="
echo "PORT|SERVICE|PROCESS|NB_CONNEXIONS|SOURCES"
for port in $(sudo ss -tnp 2>/dev/null | grep ESTAB | awk '{print $4}' | grep -oP ':\K\d+$' | sort -n | uniq); do
echo "$listen_ports" | grep -qx "$port" || continue
svc=$(getent services "$port/tcp" 2>/dev/null | awk '{print $1}')
proc=$(sudo ss -tlnp 2>/dev/null | grep ":$port " | grep -oP '"\K[^"]+' | head -1)
count=$(sudo ss -tnp 2>/dev/null | grep ESTAB | awk '{print $4}' | grep -P ":${port}$" | wc -l)
sources=$(sudo ss -tnp 2>/dev/null | grep ESTAB | awk -v p=":${port}$" '$4 ~ p {print $5}' | grep -oP '^[^:]+' | sort -u | head -10 | tr '\n' ',' | sed 's/,$//')
echo "$port|${svc:--}|${proc:--}|$count|${sources:--}"
done
# ── 2.6 Resume flux sortants ──
echo ""
echo "=== 2.6 RESUME FLUX SORTANTS (par destination:port) ==="
echo "DEST_IP|DEST_PORT|SERVICE|PROCESS|NB_CONNEXIONS"
sudo ss -tnp 2>/dev/null | grep ESTAB | while read state recvq sendq local remote info; do
local_port=$(echo "$local" | grep -oP ':\K[0-9]+$')
echo "$listen_ports" | grep -qx "$local_port" && continue
echo "$remote|$(echo "$info" | grep -oP '"\K[^"]+' | head -1)"
done | sort | uniq -c | sort -rn | head -50 | while read count dest_info; do
dest_ip=$(echo "$dest_info" | grep -oP '^\S+(?=:\d+)')
dest_port=$(echo "$dest_info" | grep -oP ':\K\d+(?=\|)')
proc=$(echo "$dest_info" | awk -F'|' '{print $2}')
svc=$(getent services "$dest_port/tcp" 2>/dev/null | awk '{print $1}')
dns=$(timeout 2 host "$dest_ip" 2>/dev/null | grep -oP 'pointer \K\S+' | sed 's/\.$//' | head -1)
if [ -n "$dns" ]; then
echo "$dest_ip ($dns)|$dest_port|${svc:--}|${proc:--}|$count"
else
echo "$dest_ip|$dest_port|${svc:--}|${proc:--}|$count"
fi
done
# ── 2.7 Connexions en attente ──
echo ""
echo "=== 2.7 CONNEXIONS EN ATTENTE ==="
echo "STATE|COUNT"
for st in TIME-WAIT CLOSE-WAIT FIN-WAIT-1 FIN-WAIT-2 SYN-SENT SYN-RECV LAST-ACK CLOSING; do
cnt=$(sudo ss -tn state "$st" 2>/dev/null | grep -c -v 'State')
[ "$cnt" -gt 0 ] && echo "$st|$cnt"
done
# ── 2.8 Stats reseau ──
echo ""
echo "=== 2.8 STATISTIQUES RESEAU ==="
echo "METRIC|VALUE"
echo "TCP ESTABLISHED|$(sudo ss -tn state established 2>/dev/null | grep -c -v 'State')"
echo "TCP LISTEN|$(sudo ss -tln 2>/dev/null | grep -c LISTEN)"
echo "UDP LISTEN|$(sudo ss -uln 2>/dev/null | grep -c -v 'State')"
# ── 2.9 Trafic par interface ──
echo ""
echo "=== 2.9 TRAFIC PAR INTERFACE ==="
echo "INTERFACE|RX_BYTES|RX_PACKETS|RX_ERRORS|TX_BYTES|TX_PACKETS|TX_ERRORS"
sudo cat /proc/net/dev 2>/dev/null | tail -n+3 | while read line; do
iface=$(echo "$line" | awk -F: '{print $1}' | tr -d ' ')
stats=$(echo "$line" | awk -F: '{print $2}')
rx_bytes=$(echo "$stats" | awk '{print $1}')
rx_pkt=$(echo "$stats" | awk '{print $2}')
rx_err=$(echo "$stats" | awk '{print $3}')
tx_bytes=$(echo "$stats" | awk '{print $9}')
tx_pkt=$(echo "$stats" | awk '{print $10}')
tx_err=$(echo "$stats" | awk '{print $11}')
[ "$iface" = "lo" ] && continue
rx_h=$(numfmt --to=iec "$rx_bytes" 2>/dev/null || echo "${rx_bytes}B")
tx_h=$(numfmt --to=iec "$tx_bytes" 2>/dev/null || echo "${tx_bytes}B")
echo "$iface|$rx_h|$rx_pkt|$rx_err|$tx_h|$tx_pkt|$tx_err"
done
# ── 2.10 Firewall ──
echo ""
echo "=== 2.10 FIREWALL ==="
if command -v iptables &>/dev/null; then
echo "--- POLICY ---"
for chain in INPUT OUTPUT FORWARD; do
policy=$(iptables -L "$chain" -n 2>/dev/null | head -1 | grep -oP 'policy \K\w+')
echo "$chain|$policy"
done
echo "--- INPUT ---"
echo "NUM|TARGET|PROTO|SOURCE|DEST|PORT|INFO"
iptables -L INPUT -n -v --line-numbers 2>/dev/null | tail -n+3 | head -30 | while read num pkts bytes target prot opt in out source dest rest; do
port=$(echo "$rest" | grep -oP '(dpt|dpts):\K\S+' | head -1)
echo "$num|$target|$prot|$source|$dest|${port:--}|$rest"
done
echo "--- OUTPUT ---"
echo "NUM|TARGET|PROTO|SOURCE|DEST|PORT|INFO"
iptables -L OUTPUT -n -v --line-numbers 2>/dev/null | tail -n+3 | head -30 | while read num pkts bytes target prot opt in out source dest rest; do
port=$(echo "$rest" | grep -oP '(dpt|dpts):\K\S+' | head -1)
echo "$num|$target|$prot|$source|$dest|${port:--}|$rest"
done
else
echo "iptables non disponible"
fi
if sudo systemctl is-active firewalld &>/dev/null 2>&1; then
echo "--- FIREWALLD ---"
echo "ZONE|SERVICES|PORTS"
for zone in $(firewall-cmd --get-active-zones 2>/dev/null | grep -v '^\s' | grep -v '^$'); do
svcs=$(firewall-cmd --zone="$zone" --list-services 2>/dev/null | tr ' ' ',')
ports=$(firewall-cmd --zone="$zone" --list-ports 2>/dev/null | tr ' ' ',')
echo "$zone|${svcs:--}|${ports:--}"
done
fi
##############################################################
# PARTIE 3 — CORRELATION
##############################################################
echo ""
echo "========================================================"
echo " PARTIE 3 — CORRELATION PROCESS ↔ PORTS ↔ FLUX"
echo "========================================================"
echo ""
echo "=== 3.1 MATRICE PROCESS → PORTS → CONNEXIONS ==="
echo "PROCESS|USER|PID|LISTEN_PORTS|CONN_IN|CONN_OUT|REMOTE_DESTINATIONS"
# Pour chaque process qui ecoute sur un port
sudo ss -tlnp 2>/dev/null | grep LISTEN | while read state recvq sendq local peer info; do
pid=$(echo "$info" | grep -oP 'pid=\K[0-9]+' | head -1)
proc=$(echo "$info" | grep -oP '"\K[^"]+' | head -1)
[ -z "$pid" ] && continue
port=$(echo "$local" | grep -oP ':\K[0-9]+$')
echo "$pid|$proc|$port"
done | sort -t'|' -k1,1n -u | while IFS='|' read pid proc port; do
user=$(sudo stat -c %U /proc/$pid 2>/dev/null)
# Tous les ports en ecoute pour ce PID
ports=$(sudo ss -tlnp 2>/dev/null | grep "pid=$pid," | grep -oP '\S+:\K\d+(?=\s)' | sort -un | tr '\n' ',' | sed 's/,$//')
# Connexions entrantes sur ces ports
conn_in=0
for p in $(echo "$ports" | tr ',' ' '); do
c=$(sudo ss -tnp 2>/dev/null | grep ESTAB | awk '{print $4}' | grep -c ":${p}$")
conn_in=$((conn_in + c))
done
# Connexions sortantes de ce PID
conn_out=$(sudo ss -tnp 2>/dev/null | grep ESTAB | grep "pid=$pid," | while read st rq sq lc rm inf; do
lp=$(echo "$lc" | grep -oP ':\K\d+$')
echo "$listen_ports" | grep -qx "$lp" || echo OUT
done | wc -l)
# Destinations sortantes
dests=$(sudo ss -tnp 2>/dev/null | grep ESTAB | grep "pid=$pid," | awk '{print $5}' | sort -u | head -5 | tr '\n' ',' | sed 's/,$//')
echo "$proc|${user:--}|$pid|$ports|$conn_in|$conn_out|${dests:--}"
done
# Processus avec connexions sortantes mais sans port en ecoute
echo ""
echo "=== 3.2 PROCESS SORTANTS UNIQUEMENT (pas de port en ecoute) ==="
echo "PROCESS|USER|PID|DESTINATIONS"
sudo ss -tnp 2>/dev/null | grep ESTAB | while read state recvq sendq local remote info; do
pid=$(echo "$info" | grep -oP 'pid=\K[0-9]+' | head -1)
proc=$(echo "$info" | grep -oP '"\K[^"]+' | head -1)
[ -z "$pid" ] && continue
local_port=$(echo "$local" | grep -oP ':\K[0-9]+$')
# Verifier si ce process n'ecoute PAS
sudo ss -tlnp 2>/dev/null | grep "pid=$pid," >/dev/null && continue
echo "$pid|$proc|$remote"
done | sort -t'|' -k1,1n -k3 | awk -F'|' '{
if ($1 != prev_pid) {
if (prev_pid != "") print prev_pid"|"prev_proc"|"dests
prev_pid=$1; prev_proc=$2; dests=$3
} else {
dests=dests","$3
}
} END { if (prev_pid != "") print prev_pid"|"prev_proc"|"dests }' | while IFS='|' read pid proc dests; do
user=$(sudo stat -c %U /proc/$pid 2>/dev/null)
echo "$proc|${user:--}|$pid|$dests"
done
echo ""
echo "########################################################"
echo "# FIN AUDIT — $HOSTNAME$(date '+%H:%M:%S')"
echo "########################################################"