Deprecated Linux commands are why ifconfig throws "command not found" on a fresh server. Nothing is broken. Those classics were retired, and their replacements, mostly the ip command from iproute2, plus ss, grep -E and systemctl, are already on your system.
Modern Replacement Syntax
LinuxTeck.com
ss [OPTIONS] [FILTER]
grep -E PATTERN [FILE...]
systemctl [COMMAND] [UNIT]
The first time I SSH'd into a new Ubuntu cloud box and typed ifconfig out of pure muscle memory, I honestly thought the image was broken. It wasn't, net-tools just hadn't shipped by default for years. Below you'll find 17 deprecated Linux commands, each next to its replacement, with real output, so you can retrain your fingers and fix old scripts. If you like this kind of upgrade, the modern Linux tools list is worth a look too.
How to Install Replacements for Deprecated Linux Commands
Good news, you probably have the replacements for most deprecated Linux commands already. iproute2 ships on basically every distro. iw, ethtool, rsync and chrony sit in the standard repos if a minimal image left them out. Heads up on Ubuntu: installing chrony removes systemd-timesyncd, which is expected.
LinuxTeck.com
linuxteck@ubuntu:~$ sudo apt install iproute2 iw ethtool rsync chrony
# RHEL / Rocky Linux / AlmaLinux / Fedora
linuxteck@rocky:~$ sudo dnf install iproute iw ethtool rsync chrony
# Arch Linux
linuxteck@arch:~$ sudo pacman -S iproute2 iw ethtool rsync chrony
# openSUSE
linuxteck@opensuse:~$ sudo zypper install iproute2 iw ethtool rsync chrony
# Verify iproute2
linuxteck@ubuntu:~$ ip -V
Building dependency tree... Done
Reading state information... Done
iproute2 is already the newest version (6.1.0-1ubuntu6).
ethtool is already the newest version (1:6.7-1build1).
rsync is already the newest version (3.2.7-1ubuntu1).
The following packages will be REMOVED:
systemd-timesyncd
The following NEW packages will be installed:
chrony iw
0 upgraded, 2 newly installed, 1 to remove and 0 not upgraded.
Setting up iw (6.7-1) ...
Setting up chrony (4.5-1ubuntu4) ...
ip utility, iproute2-6.1.0, libbpf 1.3.0
1. Replace ifconfig With ip addr to Check IP Addresses
Of all the deprecated Linux commands, this is the one that trips everyone up. Spin up a minimal Ubuntu 24.04 server on pretty much any host, a Verpex VPS or a local VM, and net-tools just isn't there. ip addr show is the direct swap, and -br gives you a tidy one-line-per-interface view.
LinuxTeck.com
linuxteck@ubuntu:~$ ip addr show enp1s0
linuxteck@ubuntu:~$ ip -br addr
link/ether 52:54:00:3a:7c:19 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.10/24 brd 192.168.1.255 scope global enp1s0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe3a:7c19/64 scope link
valid_lft forever preferred_lft forever
lo UNKNOWN 127.0.0.1/8 ::1/128
enp1s0 UP 192.168.1.10/24 fe80::5054:ff:fe3a:7c19/64
You can shorten it to ip a once it sticks. For a wider tour of the tools around it, see these Linux networking commands.
2. Bring an Interface Up or Down With ip link
ifconfig enp2s0 down becomes ip link set enp2s0 down. Same idea, just a different verb order. Try it on a spare interface, not the one your SSH session rides on.
LinuxTeck.com
linuxteck@ubuntu:~$ sudo ip link set enp2s0 down
linuxteck@ubuntu:~$ ip -br link show enp2s0
linuxteck@ubuntu:~$ sudo ip link set enp2s0 up
linuxteck@ubuntu:~$ ip -br link show enp2s0
enp2s0 UP 52:54:00:8e:21:4d <BROADCAST,MULTICAST,UP,LOWER_UP>
Watch for LOWER_UP. That flag means the cable (or virtual link) actually has carrier, not just that the interface is enabled.
3. Change an IP Address Without Stacking a Second One
Before you touch any address on a remote box, check one kernel setting. When the primary IP on an interface is deleted, Linux also drops every secondary IP in that subnet unless promote_secondaries is on. Lots of systemd based distros already set it to 1, but I'd never bet an SSH session on that. Check it and turn it on first.
LinuxTeck.com
linuxteck@ubuntu:~$ sysctl net.ipv4.conf.enp1s0.promote_secondaries
linuxteck@ubuntu:~$ sudo sysctl -w net.ipv4.conf.enp1s0.promote_secondaries=1
net.ipv4.conf.enp1s0.promote_secondaries = 1
Now the mistake I see most from people coming off ifconfig. With ifconfig, setting a new address replaced the old one. So they run ip addr add expecting the same thing.
LinuxTeck.com
linuxteck@ubuntu:~$ sudo ip addr add 192.168.1.50/24 dev enp1s0
linuxteck@ubuntu:~$ ip -4 addr show enp1s0
inet 192.168.1.10/24 brd 192.168.1.255 scope global enp1s0
valid_lft forever preferred_lft forever
inet 192.168.1.50/24 scope global secondary enp1s0
valid_lft forever preferred_lft forever
Common Mistake:
ip addr add adds, it never replaces. Now the box answers on two addresses and the old one is still primary. ip addr replace won't help either, it only updates an address that already exists and never swaps one IP for another. You have to delete the old address yourself. Skip the sysctl step above and that delete takes 192.168.1.50 down with it, along with your SSH session.
LinuxTeck.com
linuxteck@ubuntu:~$ ip -4 addr show enp1s0
inet 192.168.1.50/24 scope global enp1s0
valid_lft forever preferred_lft forever
192.168.1.50 got promoted to primary instead of vanishing. If you're logged in through 192.168.1.10 itself, deleting it still drops you, so reconnect on the new address first or do it from the console. And nothing done with ip survives a reboot, make it permanent with netplan on Ubuntu or nmcli on RHEL and Rocky Linux (see example 14).
4. Replace route With ip route
route -n becomes ip route show, and adding a route is ip route add. The bonus you didn't get before is ip route get, which tells you exactly which path the kernel will pick for a destination.
LinuxTeck.com
linuxteck@ubuntu:~$ ip route show
# Old: route add -net 10.20.0.0/16 gw 192.168.1.254
linuxteck@ubuntu:~$ sudo ip route add 10.20.0.0/16 via 192.168.1.254 dev enp1s0
linuxteck@ubuntu:~$ ip route get 10.20.5.9
192.168.1.0/24 dev enp1s0 proto kernel scope link src 192.168.1.10
10.20.5.9 via 192.168.1.254 dev enp1s0 src 192.168.1.10 uid 1000
cache
When someone says "traffic is going the wrong way", ip route get settles the argument in about two seconds.
5. Replace arp With ip neigh
The ARP table lives under ip neigh now. It also shows neighbor state, which arp never did well.
LinuxTeck.com
linuxteck@ubuntu:~$ ip neigh show
# Old: arp -d 192.168.1.40
linuxteck@ubuntu:~$ sudo ip neigh del 192.168.1.40 dev enp1s0
192.168.1.40 dev enp1s0 lladdr 52:54:00:c1:0b:77 STALE
192.168.1.77 dev enp1s0 FAILED
A FAILED entry usually means the host is down or you're on the wrong VLAN. Handy when a server "can't reach" a neighbor.
6. Replace netstat With ss to Find Listening Ports
netstat -tulpn maps almost flag for flag to ss -tulpn. ss reads straight from the kernel, so it's noticeably faster on busy boxes with thousands of sockets. Run it with sudo or the Process column stays empty.
LinuxTeck.com
linuxteck@ubuntu:~$ sudo ss -tulpn
# Only established SSH sessions
linuxteck@ubuntu:~$ ss -tn state established '( sport = :22 )'
udp UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=612,fd=13))
tcp LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=612,fd=14))
tcp LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1034,fd=3))
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1288,fd=6))
tcp LISTEN 0 4096 [::]:22 [::]:* users:(("sshd",pid=1034,fd=4))
Recv-Q Send-Q Local Address:Port Peer Address:Port
0 0 192.168.1.10:22 192.168.1.25:51844
0 36 192.168.1.10:22 192.168.1.31:60212
The filter syntax is where ss really pulls ahead. There's a lot more in our full ss command guide, and if you just need to know which process uses a port, that one has you covered.
7. Replace netstat -i With ip -s link
Interface counters used to come from netstat -i. Now it's ip -s link. The other netstat modes moved too: -r is ip route, -g is ip maddr, and -s is nstat.
LinuxTeck.com
linuxteck@ubuntu:~$ ip -s link show enp1s0
link/ether 52:54:00:3a:7c:19 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped missed mcast
884213904 712455 0 14 0 2231
TX: bytes packets errors dropped carrier collsns
96544120 301877 0 0 0 0
Climbing errors or dropped numbers on RX are worth chasing. Bad cable, duplex mismatch, or a ring buffer that's too small.
8. Replace iwconfig With iw for Wireless Info
iwconfig belongs to wireless-tools, which hasn't really moved in a long time and doesn't understand newer Wi-Fi standards properly. iw talks nl80211 and shows the real link details.
LinuxTeck.com
linuxteck@ubuntu:~$ iw dev
linuxteck@ubuntu:~$ iw dev wlp2s0 link
Interface wlp2s0
ifindex 3
wdev 0x1
addr a4:c3:f0:5e:12:8b
ssid HomeLab-5G
type managed
channel 44 (5220 MHz), width: 80 MHz, center1: 5210 MHz
txpower 22.00 dBm
Connected to 7c:10:c9:4d:aa:31 (on wlp2s0)
SSID: HomeLab-5G
freq: 5220
signal: -52 dBm
rx bitrate: 866.7 MBit/s VHT-MCS 9 80MHz short GI VHT-NSS 2
tx bitrate: 780.0 MBit/s VHT-MCS 8 80MHz short GI VHT-NSS 2
Anything around -50 to -60 dBm is a solid signal. Past -75 and you'll start feeling it.
9. Replace mii-tool With ethtool for Link Speed
mii-tool came from net-tools too, and it only knows older PHYs well. ethtool reports speed, duplex and link state on anything modern.
LinuxTeck.com
linuxteck@rocky:~$ sudo ethtool enp1s0
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Speed: 1000Mb/s
Duplex: Full
Auto-negotiation: on
Port: Twisted Pair
Link detected: yes
If a gigabit server shows Speed: 100Mb/s, check the cable or switch port before you blame the application.
10. Replace egrep and fgrep With grep -E and grep -F
Since GNU grep 3.8, egrep and fgrep print an "obsolescent" warning every single time. Harmless at the prompt, annoying in cron mail. The fix is just the flag. I'm piping from journalctl here because Debian 12 and plenty of minimal images don't ship /var/log/syslog anymore, the journal is where the logs live.
LinuxTeck.com
linuxteck@ubuntu:~$ journalctl -u nginx --no-pager | egrep 'error|fail' | head -2
linuxteck@ubuntu:~$ journalctl -u nginx --no-pager | grep -E 'error|fail' | head -2
# Old: fgrep '[ERROR]' /var/log/myapp/app.log
linuxteck@ubuntu:~$ grep -F '[ERROR]' /var/log/myapp/app.log | head -2
Sep 22 09:14:02 web01 systemd[1]: nginx.service: Failed with result 'exit-code'.
Sep 22 09:14:02 web01 systemd[1]: Failed to start nginx.service - A high performance web server.
Sep 22 09:14:02 web01 systemd[1]: nginx.service: Failed with result 'exit-code'.
Sep 22 09:14:02 web01 systemd[1]: Failed to start nginx.service - A high performance web server.
Sep 22 09:13:58 web01 myapp[2211]: [ERROR] upstream timed out while reading response header
Sep 22 09:14:01 web01 myapp[2211]: [ERROR] connect() failed (111: Connection refused)
-F matters with patterns like [ERROR], since the brackets are otherwise read as a regex character class. More pattern tricks in how Bash uses grep for text processing.
11. Replace service and chkconfig With systemctl
On any systemd distro, service and chkconfig are just wrappers now. On Rocky Linux you can actually watch chkconfig hand the job over.
LinuxTeck.com
linuxteck@rocky:~$ sudo chkconfig httpd on
# New way, enable and start in one go
linuxteck@rocky:~$ sudo systemctl enable --now httpd
linuxteck@rocky:~$ systemctl is-enabled httpd; systemctl is-active httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service -> /usr/lib/systemd/system/httpd.service.
enabled
active
enable --now is the one to remember. If a unit refuses to start after that, this guide on how to fix systemd service errors walks through the usual suspects.
12. Replace apt-key With a signed-by Keyring
apt-key trusted a key for every repo on the system, which was a real security hole. It now prints a deprecation warning on Ubuntu 24.04, and its own man page says Debian 12 and Ubuntu 24.04 are the last releases that ship it. Store the key per repo and point to it with signed-by.
LinuxTeck.com
linuxteck@ubuntu:~$ sudo install -d -m 0755 /etc/apt/keyrings
linuxteck@ubuntu:~$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
linuxteck@ubuntu:~$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list
linuxteck@ubuntu:~$ sudo apt update
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Hit:2 http://security.ubuntu.com/ubuntu noble-security InRelease
Get:3 https://download.docker.com/linux/ubuntu noble InRelease [48.8 kB]
Get:4 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages [31.2 kB]
Fetched 80.0 kB in 1s (92.4 kB/s)
Reading package lists... Done
The $(...) bits fill in your architecture and release codename, so the same line works on 22.04, 24.04 or whatever you're on. On Debian, swap /linux/ubuntu for /linux/debian in both URLs.
Security Warning:
Keys already added with apt-key live in /etc/apt/trusted.gpg and are trusted for every repo. Run apt-key list once, move what you still need into /etc/apt/keyrings/, and clean the rest out.
13. Replace yum With dnf on RHEL and Rocky Linux
yum still "works" on RHEL 8, 9 and 10, but it's just a symlink to dnf. Ask both for a version and you get the same answer. Old muscle memory is fine at the prompt. For docs and new scripts, write dnf. On Fedora 41 and newer, dnf itself is now dnf5, so the output looks a little different there.
LinuxTeck.com
linuxteck@rocky:~$ dnf --version | head -1
linuxteck@rocky:~$ sudo dnf install -y tmux
4.14.0
Last metadata expiration check: 0:12:41 ago on Tue 22 Sep 2026 10:02:11 AM IST.
Dependencies resolved.
Installing:
tmux x86_64 3.2a-5.el9 baseos 474 k
Complete!
Coming from the Debian side? The dnf vs apt comparison maps the common commands between the two.
14. Replace ifup, ifdown and network-scripts With nmcli
RHEL 9 and Rocky Linux 9 dropped the legacy network-scripts package, and ifcfg files are deprecated in favor of NetworkManager keyfiles. If ifup still exists on your box, it's a thin wrapper around nmcli. This is also the persistent fix for the IP change in example 3.
LinuxTeck.com
linuxteck@rocky:~$ nmcli -t -f NAME,DEVICE connection show --active
linuxteck@rocky:~$ sudo nmcli connection modify enp1s0 ipv4.method manual ipv4.addresses 192.168.1.50/24 ipv4.gateway 192.168.1.1 ipv4.dns 1.1.1.1
linuxteck@rocky:~$ sudo nmcli connection up enp1s0
lo:lo
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)
Production Tip:
On a remote server, chain the modify and up into one line or run it inside tmux. If the session drops halfway through a network change, you want the second half to still run.
15. Replace Legacy scp Transfers With rsync or sftp
The scp command itself isn't gone. Since OpenSSH 9.0 it quietly uses the SFTP protocol, because the old scp protocol was outdated and hard to fix. For big or repeat transfers, rsync is the better habit anyway, it resumes and only sends what changed.
LinuxTeck.com
linuxteck@ubuntu:~$ rsync -avP backup.tar.gz linuxteck@192.168.1.20:/srv/backups/
linuxteck@ubuntu:~$ ssh -V
backup.tar.gz
734,003,200 100% 98.41MB/s 0:00:07 (xfr#1, to-chk=0/1)
sent 734,182,441 bytes received 35 bytes 91,772,809.50 bytes/sec
total size is 734,003,200 speedup is 1.00
OpenSSH_9.6p1 Ubuntu-3ubuntu13.5, OpenSSL 3.0.13 30 Jan 2024
If an ancient remote server rejects the new behavior, scp -O forces the legacy protocol. Pair rsync with passwordless SSH login and it drops straight into cron.
Production Tip:
SSH on a custom port? This is where old scp -P 2222 users get stuck, since rsync has no -P for ports (-P means progress plus partial). Pass the port through ssh instead: rsync -avP -e 'ssh -p 2222' backup.tar.gz linuxteck@192.168.1.20:/srv/backups/
16. Replace ntpdate With chronyc
ntpdate was removed from RHEL 8 onward. chrony handles the one-shot sync it used to do, plus the ongoing sync.
LinuxTeck.com
linuxteck@rocky:~$ sudo chronyc makestep
linuxteck@rocky:~$ chronyc tracking
Reference ID : A29FC87B (time.cloudflare.com)
Stratum : 4
Ref time (UTC) : Tue Sep 22 04:41:17 2026
System time : 0.000012345 seconds fast of NTP time
Last offset : +0.000008911 seconds
RMS offset : 0.000211487 seconds
Frequency : 12.482 ppm slow
Skew : 0.044 ppm
Root delay : 0.018922315 seconds
Leap status : Normal
Leap status : Normal means you're synced. "Not synchronised" means chrony can't reach any source, usually a firewall blocking UDP 123.
17. Find Deprecated Linux Commands Hiding in Your Scripts
This is the real-world payoff. Old scripts are where deprecated Linux commands actually hurt you, usually on the day you migrate to a fresh server. Sweep your script directory first.
LinuxTeck.com
/opt/scripts/health_check.sh:22:netstat -tulpn | grep -q ':3306' || echo "MySQL down"
/opt/scripts/log_scan.sh:8:egrep -i "timeout|refused" /var/log/nginx/error.log
/opt/scripts/add_repo.sh:5:curl -fsSL https://repo.example.com/key.gpg | apt-key add -
Then rewrite each hit. Here's line 14 done with ip, which gives you a clean address with no net-tools dependency:
LinuxTeck.com
linuxteck@ubuntu:~$ echo "$IP"
Production Tip:
Add a guard at the top of scripts that must run everywhere, something like command -v ip >/dev/null || { echo "iproute2 missing"; exit 1; }. Failing loudly on line one beats a half-run script at 3 AM.
Questions I Get Asked About This All the Time
Can I still install ifconfig and netstat if I really need them?
Yep. sudo apt install net-tools on Ubuntu or Debian, sudo dnf install net-tools on RHEL and Rocky Linux. Fine for a quick look. Just know ifconfig only shows one address per interface unless it has a label, so on a box with secondary IPs it quietly hides some of them. Don't build new scripts on it.
Why were these networking commands deprecated in the first place?
net-tools uses the old ioctl interface and saw almost no real development for years. It doesn't understand things like multiple addresses per interface, policy routing or network namespaces. iproute2 talks to the kernel over netlink, so it keeps up with new features.
Is nslookup deprecated too?
No. It was flagged as deprecated a long time ago, then that got reversed, and it still ships with the bind utils package. Most admins reach for dig when troubleshooting because the output is more complete. There's more on that in our DNS troubleshooting guide.
Will deprecated Linux commands break my existing scripts?
Depends which one. egrep keeps working but spams warnings to stderr. ifconfig breaks the moment the script lands on a minimal image without net-tools. apt-key is the nasty one, it simply isn't there on newer releases, so repo setup scripts fail hard. Run the grep audit from example 17 before any migration.
Conclusion
Most of these swaps come down to ip, ss, grep flags and systemctl, and after a week or so they stop feeling new. Clean up your scripts now, before a fresh server does it for you. For the bigger picture on networking day to day, the Linux network administration guide is a good next read. Which of these deprecated Linux commands was hardest for you to give up? Share your experience in the comments below.
From your first terminal command to advanced sysadmin skills. Every guide here is written in plain English with real examples you can run right now.
