Here is my latest website creation. Interestingly, this one is hosted on CloudFlare.
The event is over, and it went well. Photos of the event are available at https://www.centennial326.org
Every great genius needs an assistant. Batman has Alfred. Sherlock Holmes has Watson. Doc Brown had Marty, whether Marty wanted the job or not.
Tony Stark had DUM-E.
And honestly, poor DUM-E deserved better.
DUM-E, pronounced “dummy,” is the robotic arm in Tony Stark’s lab who seems to exist mainly to be yelled at, threatened, mocked, and occasionally blamed for doing exactly what he was programmed to do. His most memorable job is standing by with a fire extinguisher while Tony tests incredibly dangerous experimental technology in a private garage like OSHA is just a rumor.
And when Tony catches on fire, crashes into walls, or nearly vaporizes himself?
DUM-E acts.
He blasts Tony with the fire extinguisher.
This is not incompetence. This is commitment.
Let’s be fair to DUM-E. Tony Stark’s lab is not a normal workplace.
Most assistants are asked to schedule meetings, order lunch, or prepare reports. DUM-E’s job description appears to include:
Watching Tony build weapons-grade technology in his basement
Remaining calm during explosions
Handling emergency fire suppression
Assisting with impossible engineering projects
Enduring constant verbal abuse
Not developing a robot union
And despite all of that, DUM-E shows up.
Every time Tony is about to do something reckless, DUM-E is there. Quietly. Faithfully. Fire extinguisher ready.
Tony, of course, does not appreciate this. Instead, he treats DUM-E like the world’s worst intern. He threatens to donate him to a community college. He calls him useless. He acts annoyed when DUM-E tries to save his life.
This is classic Tony Stark behavior. He builds a loyal robot assistant, gives it just enough personality to be endearing, then spends years emotionally bullying it for not being Jarvis.
The joke is that DUM-E is clumsy. He is not smooth like Jarvis. He is not sleek like Friday. He does not speak in a calm British voice or run complex battlefield simulations.
But DUM-E is not dumb.
DUM-E understands the assignment. Tony catches on fire, DUM-E extinguishes the fire. Tony flies into a wall, DUM-E responds. Tony behaves like a man who has never heard the phrase “controlled test environment,” DUM-E prepares for disaster.
In any other workplace, DUM-E would be Employee of the Month.
At Stark Industries, he gets insulted by a billionaire in a tank top.
What makes DUM-E funny is also what makes him strangely sad. He is always trying to help. He is never malicious. He is not rebelling, scheming, or malfunctioning in some dramatic way. He is simply over-eager, awkward, and loyal.
That is why audiences love him.
DUM-E is the robot version of the person at work who means well, makes things worse by accident, then gets blamed by the boss who created the problem in the first place.
Tony is the guy testing rocket boots indoors.
DUM-E is the guy holding the fire extinguisher.
Somehow, Tony thinks DUM-E is the problem.
For all the sarcasm, Tony does seem to care about DUM-E. That is part of the charm. Tony may threaten him, scold him, and act like he is one bad move away from being recycled, but DUM-E remains part of the lab.
That matters.
Tony Stark surrounds himself with machines, but he does not build lifeless tools. His creations have quirks. Jarvis has wit. The suits have style. DUM-E has anxious golden retriever energy and a fire extinguisher.
DUM-E helps make Tony’s lab feel less like a sterile high-tech facility and more like a messy, brilliant, dangerous home workshop. He is part assistant, part pet, part safety system, and part emotional support machinery.
He is family, even if Tony would never admit it without making a joke.
DUM-E may not be the smartest machine Tony Stark ever built, but he might be one of the most loyal. He stood beside Tony before the Avengers, before the world-saving, before the clean corporate labs and the polished superhero image.
He was there in the garage.
He was there with the extinguisher.
He was there when Tony was still figuring out how to become Iron Man.
So maybe DUM-E is not tragic because Tony insults him. Maybe DUM-E is tragic because he represents every loyal helper who never gets enough credit. He is the overlooked assistant, the unpaid intern, the nervous coworker trying to prevent disaster while the genius in charge creates more of it.
DUM-E is not just comic relief.
DUM-E is a hero.
A clumsy hero, yes. A hero who may fire-extinguish first and ask questions never. But a hero all the same.
And the next time Tony Stark calls him useless, someone should remind him that the richest genius on Earth still needed a robot arm standing nearby, ready to put him out when his own brilliance caught fire.
The Rod of Asclepius is the older and more accurate symbol of medicine. It shows one snake wrapped around a plain staff, with no wings. Asclepius was the Greek god associated with healing, medicine, and physicians. Because of that connection, his serpent-entwined staff became a lasting symbol of medical care and the healing arts.
The caduceus, by contrast, shows two snakes wrapped around a winged staff. This was the staff of Hermes, known to the Romans as Mercury. Hermes was the messenger of the gods, but he was also associated with travelers, merchants, trade, language, diplomacy, thievery, and cunning. In other words, the caduceus originally had more to do with communication, commerce, negotiation, and trickery than with healing.
The confusion became especially common in the United States. In 1902, the U.S. Army Medical Corps adopted the caduceus as an insignia, even though the Rod of Asclepius was the more traditional medical symbol. Over time, the caduceus became widely recognized in America as a medical emblem, despite its earlier association with Hermes rather than Asclepius.
The easiest way to remember the difference is simple: one snake means medicine; two snakes and wings mean Hermes. The Rod of Asclepius symbolizes healing and physicians. The caduceus points to messengers, merchants, travel, negotiation, and clever speech.
So the next time you see a medical logo with two snakes and wings, you are not looking at the ancient symbol of medicine. You are looking at a symbol that history borrowed, confused, and never quite gave back.
Once within a server dreary, while I pondered, weak and weary,
Over backups, logs, and folders I had trusted long before,
Came a clicking, faintly tapping, like some tiny demon rapping,
Rapping from the drive bay’s darkness, whispering of things in store.
“’Tis a cable,” then I muttered, “loose behind the chassis door.”
Only this, and nothing more.
Yet the volume mounted never, though I begged with grim endeavor,
Though I ran the sacred commands I had often run before.fsck cried out in broken meter, SMART grew colder, death grew sweeter,
Every sector turned a traitor, every block a bolted door.
Then the kernel, pale and mocking, carved my doom into its lore:
“Unknown error. Read no more.”
Deep into that disk I glowered, as the midnight slowly soured,
Dreaming dreams of lost directories vanished from the spinning core.
Photos, scripts, and ancient writing, tax returns and memes delighting,
All entombed in silent platters I may nevermore restore.
Then my soul cried, “Can I save them?”
Quoth the syslog: “Nevermore.”
With Apologies to the ghost of Edgar Allan Poe.
I recently added a managed UPS to a Linux server in my lab and wanted the server to do more than just sit on battery backup. I wanted the server to detect the UPS, monitor the battery status, send email alerts, provide a web status page, and shut down cleanly if power was out for too long.
The UPS I used was a CyberPower CP1500PFCLCD PFC Sinewave UPS Battery Backup and Surge Protector, 1500VA/1000W, 12 Outlets, AVR, Mini Tower, UL Certified
Amazon product page:
https://www.amazon.com/CyberPower-CP1500PFCLCD-Sinewave-Outlets-Mini-Tower/dp/B00429N19W
This post walks through the setup in a lab environment using Linux, Network UPS Tools, systemd, Nginx, and a simple notification script.
The lab server used for this setup was running:
Linux distribution: LMDE 7 “Gigi”
Base: Debian 13 “Trixie”
UPS: CyberPower CP1500PFCLCD
UPS connection: USB cable
UPS software: Network UPS Tools, also known as NUT
Web server: Nginx
Mail relay: Local sendmail-compatible relay
The examples below use sanitized names and addresses:
UPS name: lab-ups
Server IP: 192.168.1.5
Alert email: admin@example.com
Status page: http://192.168.1.5/status/ups/
Substitute your own values where needed.
The goal was not just battery backup. I wanted useful management:
The final behavior looked like this:
First, I connected the UPS to the Linux server using the USB cable that came with the UPS.
Then I checked whether Linux could see it:
lsusb
The UPS appeared as a CyberPower USB device. Example:
Cyber Power System, Inc. CP1500PFCLCD UPS
I also checked recent kernel messages:
dmesg | tail -n 80
This confirmed that the server saw the USB device.
Network UPS Tools, or NUT, is the standard Linux toolset for monitoring UPS units.
Install it:
apt update
apt install -y nut nut-client nut-server
Then scan for USB UPS devices:
nut-scanner -U
The scan should return something similar to this:
[nutdev1]
driver = "usbhid-ups"
port = "auto"
vendorid = "0764"
productid = "0601"
product = "CP1500PFCLCDa"
vendor = "CPS"
The important line is:
driver = "usbhid-ups"
That is the driver used for many USB HID-compatible UPS units.
Edit `/etc/nut/ups.conf`:
cp /etc/nut/ups.conf /etc/nut/ups.conf.bak.$(date +%Y%m%d-%H%M%S)
cat > /etc/nut/ups.conf <<'EOF'
[lab-ups]
driver = usbhid-ups
port = auto
vendorid = 0764
productid = 0601
desc = "CyberPower CP1500PFCLCD UPS"
EOF
This defines the UPS as `lab-ups`.
For a single server connected directly to one UPS, standalone mode is appropriate.
Configure `/etc/nut/nut.conf`:
cp /etc/nut/nut.conf /etc/nut/nut.conf.bak.$(date +%Y%m%d-%H%M%S)
cat > /etc/nut/nut.conf <<'EOF'
MODE=standalone
EOF
NUT uses a local user account so `upsmon` can monitor the UPS through `upsd`.
Configure `/etc/nut/upsd.users`:
cp /etc/nut/upsd.users /etc/nut/upsd.users.bak.$(date +%Y%m%d-%H%M%S) 2>/dev/null || true
cat > /etc/nut/upsd.users <<'EOF'
[monuser]
password = replace-this-with-a-strong-local-password
upsmon master
EOF
chmod 640 /etc/nut/upsd.users
chown root:nut /etc/nut/upsd.users
Use a real password in your own environment.
Configure `/etc/nut/upsmon.conf`:
cp /etc/nut/upsmon.conf /etc/nut/upsmon.conf.bak.$(date +%Y%m%d-%H%M%S)
cat > /etc/nut/upsmon.conf <<'EOF'
MONITOR lab-ups@localhost 1 monuser replace-this-with-a-strong-local-password master
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
NOTIFYFLAG FSD SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC
NOTIFYFLAG NOCOMM SYSLOG+WALL+EXEC
NOTIFYCMD /usr/sbin/upssched
EOF
chmod 640 /etc/nut/upsmon.conf
chown root:nut /etc/nut/upsmon.conf
This tells `upsmon` to call `upssched`, which handles timed actions.
On my setup, the UPS was detected but the driver initially could not open the USB device because of permissions.
The error looked like this:
libusb1: Could not open any HID devices: insufficient permissions on everything
No matching HID UPS found
The fix was to create a udev rule for the CyberPower UPS:
cat > /etc/udev/rules.d/62-cyberpower-ups.rules <<'EOF'
CyberPower CP1500PFCLCD UPS for NUT
SUBSYSTEM=="usb", ATTR{idVendor}=="0764", ATTR{idProduct}=="0601", MODE="0660", GROUP="nut"
SUBSYSTEM=="usb_device", ATTR{idVendor}=="0764", ATTR{idProduct}=="0601", MODE="0660", GROUP="nut"
EOF
udevadm control --reload-rules
udevadm trigger
Then unplug the UPS USB cable, wait a few seconds, and plug it back in.
Check the permissions:
lsusb | grep -i -E 'cyber|power|ups|0764'
for dev in /dev/bus/usb/*/*; do
if udevadm info -q property -n "$dev" 2>/dev/null | grep -q 'ID_VENDOR_ID=0764'; then
echo "===== $dev ====="
ls -l "$dev"
fi
done
The device should be owned by root with group `nut`.
On Debian 13, the driver runs as a systemd instance, such as:
nut-driver@lab-ups.service
Start and enable the NUT services:
systemctl daemon-reload
systemctl enable --now nut-driver-enumerator.path
systemctl enable --now nut-driver-enumerator.service
systemctl enable --now nut-server
systemctl enable --now nut-monitor
Check the driver instance:
systemctl list-units 'nut-driver*' --all --no-pager
You should see something like:
nut-driver@lab-ups.service loaded active running
Then check all three main pieces:
systemctl is-active nut-driver@lab-ups.service nut-server nut-monitor
Expected:
active
active
active
Now query the UPS:
upsc lab-ups@localhost
Useful values include:
text
battery.charge
battery.runtime
input.voltage
output.voltage
ups.load
ups.status
Example:
text
battery.charge: 100
battery.runtime: 5525
input.voltage: 120.0
output.voltage: 120.0
ups.load: 7
ups.status: OL
`OL` means the UPS is on utility power.
Common status values:
text
OL On line power
OB On battery
LB Low battery
OL CHRG On line and charging
I wanted the server to send an email when UPS events happened.
Create `/usr/local/sbin/lab-ups-notify.sh`:
cat > /usr/local/sbin/lab-ups-notify.sh <<'EOF'
!/usr/bin/env bash
TO="admin@example.com"
FROM="Lab Server <server@example.com>"
LOG="/var/log/lab-ups.log"
EVENT="${NOTIFYTYPE:-UNKNOWN}"
MESSAGE="${*:-No message supplied}"
NOW="$(date '+%Y-%m-%d %H:%M:%S %Z')"
HOST="$(hostname -f 2>/dev/null || hostname)"
UPS_STATUS="$(upsc lab-ups@localhost 2>/dev/null || true)"
{
echo "[$NOW] UPS event: $EVENT - $MESSAGE"
} >> "$LOG"
timeout 30 /usr/sbin/sendmail -t <<MAIL
From: ${FROM}
To: ${TO}
Subject: [LAB SERVER] UPS event: ${EVENT}
The lab server received a UPS event.
Time:
${NOW}
Host:
${HOST}
Event:
${EVENT}
Message:
${MESSAGE}
UPS Status:
${UPS_STATUS}
MAIL
exit 0
EOF
chmod 0755 /usr/local/sbin/lab-ups-notify.sh
Test it:
NOTIFYTYPE=TEST /usr/local/sbin/lab-ups-notify.sh "Manual UPS notification test"
If the email arrives, the notification script is working.
I did not want the server to shut down immediately for a short power blink. I wanted it to wait.
The plan was:
Create the `upssched` command script:
cat > /usr/local/sbin/lab-upssched-cmd.sh <<'EOF'
!/usr/bin/env bash
LOG="/var/log/lab-ups.log"
NOW="$(date '+%Y-%m-%d %H:%M:%S %Z')"
case "$1" in
onbatt-warning)
NOTIFYTYPE=ONBATT-WARNING /usr/local/sbin/lab-ups-notify.sh \
"The lab server has been on UPS battery power for 5 minutes."
echo "[$NOW] upssched: 5-minute on-battery warning sent" >> "$LOG"
;;
onbatt-shutdown)
NOTIFYTYPE=ONBATT-SHUTDOWN /usr/local/sbin/lab-ups-notify.sh \
"The lab server has been on UPS battery power for 30 minutes. Starting clean shutdown."
echo "[$NOW] upssched: 30-minute on-battery shutdown triggered" >> "$LOG"
/sbin/upsmon -c fsd
;;
online-recovery)
NOTIFYTYPE=ONLINE-RECOVERY /usr/local/sbin/lab-ups-notify.sh \
"Power has been restored. The lab server is back on utility power. UPS shutdown timers have been cancelled."
echo "[$NOW] upssched: online recovery email sent; shutdown timers cancelled" >> "$LOG"
;;
*)
echo "[$NOW] upssched: unknown command: $1" >> "$LOG"
;;
esac
EOF
chmod 0755 /usr/local/sbin/lab-upssched-cmd.sh
Then configure `/etc/nut/upssched.conf`:
cp /etc/nut/upssched.conf /etc/nut/upssched.conf.bak.$(date +%Y%m%d-%H%M%S) 2>/dev/null || true
cat > /etc/nut/upssched.conf <<'EOF'
CMDSCRIPT /usr/local/sbin/lab-upssched-cmd.sh
PIPEFN /run/nut/upssched.pipe
LOCKFN /run/nut/upssched.lock
AT ONBATT * START-TIMER onbatt-warning 300
AT ONBATT * START-TIMER onbatt-shutdown 1800
AT ONLINE * CANCEL-TIMER onbatt-warning
AT ONLINE * CANCEL-TIMER onbatt-shutdown
AT ONLINE * EXECUTE online-recovery
AT LOWBATT * EXECUTE onbatt-shutdown
EOF
chmod 640 /etc/nut/upssched.conf
chown root:nut /etc/nut/upssched.conf
Restart the monitor:
systemctl restart nut-monitor
Verify:
systemctl status nut-monitor --no-pager
I also wanted a simple web page to show UPS status.
Install the packages:
apt update
apt install -y nut-cgi fcgiwrap
Find the CGI files:
dpkg -L nut-cgi | grep -E 'cgi|upsstats|upsset|hosts'
On Debian, the CGI files are usually here:
/usr/lib/cgi-bin/nut/upsstats.cgi
/usr/lib/cgi-bin/nut/upsimage.cgi
/usr/lib/cgi-bin/nut/upsset.cgi
Configure `/etc/nut/hosts.conf`:
cp /etc/nut/hosts.conf /etc/nut/hosts.conf.bak.$(date +%Y%m%d-%H%M%S)
cat > /etc/nut/hosts.conf <<'EOF'
MONITOR lab-ups@localhost "Lab UPS"
EOF
Start `fcgiwrap`:
systemctl enable --now fcgiwrap.socket
systemctl status fcgiwrap.socket --no-pager
In my lab, I exposed the UPS page as a subpage of the server’s local status site:
http://192.168.1.5/status/ups/
The Nginx block looked like this:
location = /status/ups {
return 301 /status/ups/;
}
location /status/ups/ {
include fastcgi_params;
fastcgi_pass unix:/run/fcgiwrap.socket;
fastcgi_param SCRIPT_FILENAME /usr/lib/cgi-bin/nut/upsstats.cgi;
fastcgi_param SCRIPT_NAME /status/ups/;
fastcgi_param PATH_INFO "";
fastcgi_param QUERY_STRING $query_string;
add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0";
}
location = /status/ups/upsimage.cgi {
include fastcgi_params;
fastcgi_pass unix:/run/fcgiwrap.socket;
fastcgi_param SCRIPT_FILENAME /usr/lib/cgi-bin/nut/upsimage.cgi;
fastcgi_param SCRIPT_NAME /status/ups/upsimage.cgi;
fastcgi_param QUERY_STRING $query_string;
add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0";
}
Test Nginx:
nginx -t
systemctl reload nginx
Then test the page:
curl -I http://192.168.1.5/status/ups/
The detailed UPS page was available at:
http://192.168.1.5/status/ups/?host=lab-ups@localhost
Here are the main commands I use to check the UPS setup:
systemctl is-active nut-driver@lab-ups.service nut-server nut-monitor
upsc lab-ups@localhost | grep -E 'ups.status|battery.charge|battery.runtime|ups.load|input.voltage|output.voltage'
systemctl list-units 'nut-driver*' --all --no-pager
tail -n 50 /var/log/lab-ups.log
Expected UPS status on normal wall power:
ups.status: OL
After setup, the server had:
At the current low load in my lab, the UPS reported roughly 90 minutes of runtime. I chose not to run the server all the way down. Instead, the system waits 30 minutes on battery, then shuts down cleanly unless power returns first.
That gives short outages a chance to clear while still protecting the server, filesystems, and running services from an uncontrolled power loss.
A UPS is useful by itself, but it becomes much more useful when the server can talk to it. With a USB cable and Network UPS Tools, a Linux server can monitor power status, send alerts, display a web status page, and shut itself down cleanly.
For a home lab or small server rack, this is one of those upgrades that is worth doing before the next power outage.
I recently connected a Linux server in my lab directly to a Cisco Catalyst switch using a USB-to-RJ45 Cisco console cable. The goal was simple: manage the switch from the Linux command line without needing a separate laptop, USB serial adapter, or Windows terminal program.
This is a practical lab setup for anyone who works with older Cisco switches, home lab racks, or small network environments. Once the cable is connected, the Linux server can act as a permanent console workstation for the switch.
For this lab, I used the following equipment:
Linux server
Linux distribution: LMDE 7 “Gigi”
Base: Debian 13 “Trixie”
Cisco switch
Model: Cisco Catalyst WS-C2960G-8TC-L
Console cable
Cable Matters USB-to-RJ45 Cisco console cable
FTDI-based USB serial chipset
Length: 6 feet
The specific cable used was sold as a Cable Matters USB-to-RJ45 Console Cable compatible with Cisco console cables / rollover cords, and purchased from Amazon: https://www.amazon.com/dp/B078PVJ5ZQ
This kind of cable is not an Ethernet cable. The RJ45 end plugs into the console port on the Cisco switch, not into a regular Ethernet switch port.
A Cisco console connection is a serial connection. Many Cisco switches use an RJ45-style console port, but electrically it is not Ethernet.
The USB-to-RJ45 console cable includes a USB-to-serial adapter in the cable assembly. In this lab, Linux detected the USB-to-serial chipset as an FTDI device. Once detected, the system created a serial console device that could be used to connect to the Cisco switch.
The connection is straightforward:
Linux server USB port
|
| USB-to-RJ45 Cisco console cable
|
Cisco Catalyst console port
The RJ45 end must go into the console port on the Cisco switch. Do not plug it into a normal Ethernet data port.
After plugging in the USB side of the console cable, I checked whether Linux detected the USB serial chipset:
lsusb | grep -i -E 'ftdi|serial|cable|0403'
Example output:
Bus 005 Device 002: ID 0403:6001 Future Technology Devices International,
Ltd FT232 Serial (UART) IC
Then I checked the kernel log:
dmesg | grep -i -E 'ttyUSB|ftdi|usb serial' | tail -n 30
The important line was:
FTDI USB Serial Device converter now attached to ttyUSB0
That means Linux created a serial device at:
/dev/ttyUSB0
Linux also created a stable device path:
ls -l /dev/ttyUSB* /dev/serial/by-id/* 2>/dev/null
Example output:
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AH6SK75M-if00-port0 -> ../../ttyUSB0
/dev/ttyUSB0
I prefer using the /dev/serial/by-id/ path because /dev/ttyUSB0 can change if additional USB serial devices are connected later.
On the Linux server, I installed screen and minicom:
sudo apt update
sudo apt install -y screen minicom
Either tool can be used. screen is quick and simple. minicom is more purpose-built for serial console work.
Most Cisco Catalyst console ports use 9600 baud.
To connect using screen:
screen /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AH6SK75M-if00-port0 9600
After the session opens, press Enter once or twice. The Cisco prompt should appear:
Switch>
To enter privileged EXEC mode:
enable
The prompt should change to:
Switch#
At that point, the Linux server is connected to the Cisco switch console.
Cisco IOS often pauses long output with --More--. For lab documentation and troubleshooting, I usually disable paging for the current session:
terminal length 0
This does not permanently change the switch. It only affects the current console session.
Useful commands for identifying and documenting the switch include:
show version
show inventory
show running-config
show startup-config
show ip interface brief
show interfaces status
show vlan brief
show logging
In this lab, the switch was identified as:
Model: Cisco Catalyst WS-C2960G-8TC-L
IOS image: c2960-lanbasek9-mz.122-55.SE5.bin
Processor: PowerPC405
Memory: 65536K bytes
Management interface: Vlan1
Management IP method: DHCP
The switch had a DHCP-assigned management IP address on VLAN 1.
After changing Cisco IOS configuration, save the running configuration to startup configuration:
write memory
or:
copy running-config startup-config
If prompted for the destination filename, press Enter to accept the default.
Do not just close the terminal window. To cleanly disconnect from screen:
Ctrl-A
K
y
That means:
Press Ctrl-A.
Press K.
Press y to confirm.
This exits the screen session and releases the serial device.
Minicom is another good option for Cisco console access.
To connect:
minicom -D /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AH6SK75M-if00-port0 -b 9600
If the screen appears blank, press Enter once or twice.
To exit Minicom:
Ctrl-A
X
Then confirm that you want to leave Minicom.
For documentation, I like logging the whole Cisco console session to a file. This creates a record of the commands run and the output returned by the switch.
Create a log directory:
mkdir -p /root/cisco-logs
Start screen with logging enabled:
screen -L -Logfile /root/cisco-logs/catalyst-2960-$(date +%Y%m%d-%H%M%S).log \
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AH6SK75M-if00-port0 9600
Inside the Cisco session, run the commands you want to capture:
terminal length 0
show version
show inventory
show running-config
show interfaces status
show vlan brief
show ip interface brief
When finished, exit screen:
Ctrl-A
K
y
Then review the log file:
ls -lt /root/cisco-logs/
less /root/cisco-logs/catalyst-2960-*.log
This is one of the easiest ways to collect clean documentation from a Cisco switch in a lab.
Older Cisco Catalyst switches may have the built-in HTTP or HTTPS management server enabled. If you browse to the switch management IP and get a username/password prompt, that may be the switch’s internal web interface.
For an older lab switch, I prefer disabling web management unless I specifically need it:
configure terminal
no ip http server
no ip http secure-server
end
write memory
Verify:
show running-config | include ip http
Expected output:
no ip http server
no ip http secure-server
For a lab switch, console access is often enough. If remote management is needed later, configure SSH, a local admin user, an enable secret, and management access restrictions.
If Linux does not show the serial device, check:
lsusb
dmesg | grep -i -E 'ttyUSB|ftdi|usb serial'
ls -l /dev/ttyUSB* /dev/serial/by-id/* 2>/dev/null
If another program is using the serial port:
fuser -v /dev/ttyUSB0
If the screen is blank:
Press Enter.
Confirm the RJ45 connector is plugged into the console port.
Confirm the baud rate is 9600.
Try minicom if screen behaves oddly.
If the characters are garbled, the serial settings are probably wrong. Most Cisco Catalyst console ports use:
9600 baud
8 data bits
No parity
1 stop bit
No flow control
Connecting a Linux server to a Cisco Catalyst switch with a USB-to-RJ45 console cable is a simple and useful lab setup. It lets the Linux server act as a dedicated console workstation for the switch. It also makes it easy to capture switch configuration, check port status, save logs, and perform recovery work without dragging out another machine.
For a home lab, small rack, or learning environment, this is a practical and inexpensive way to manage older Cisco gear from the Linux command line.
Eighty-two years ago today, freedom stood on the edge of extinction, and Allied forces stormed into hell to help save the world. We will never forget the courage, the sacrifice, and the blood spilled on that fateful day.