learn_bash_from_session_data 1.0.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2270 @@
1
+ """
2
+ Enrichment data for Networking, Process/System, and Permissions commands.
3
+
4
+ This module provides use_cases, gotchas, man_url, related, difficulty, and
5
+ extra_flags for commands that have thin entries in COMMAND_DB.
6
+
7
+ Usage:
8
+ from scripts.enrichment_netproc import ENRICHMENT_DATA
9
+ # Merge into COMMAND_DB entries as needed.
10
+ """
11
+
12
+ ENRICHMENT_DATA = {
13
+
14
+ # =========================================================================
15
+ # NETWORKING COMMANDS
16
+ # =========================================================================
17
+
18
+ "nc": {
19
+ "man_url": "https://man7.org/linux/man-pages/man1/ncat.1.html",
20
+ "use_cases": [
21
+ "Test if a remote port is open with nc -zv host 443 before deploying",
22
+ "Transfer a file between machines: receiver runs nc -l -p 9999 > file.txt, sender runs nc host 9999 < file.txt",
23
+ "Create a quick ad-hoc chat between two terminals for debugging coordination",
24
+ "Pipe data into a network service for scripted testing: echo 'GET / HTTP/1.0\\r\\n\\r\\n' | nc host 80",
25
+ ],
26
+ "gotchas": [
27
+ "There are multiple incompatible netcat implementations (GNU, OpenBSD, ncat) with different flag syntax -- the -p flag behavior and -e support vary between them",
28
+ "The -e flag to execute a program on connection is disabled in many distributions for security reasons; use ncat --exec instead",
29
+ "OpenBSD netcat does not support the -p flag with -l; the port goes directly after -l",
30
+ ],
31
+ "related": ["ncat", "socat", "telnet", "curl"],
32
+ "difficulty": "intermediate",
33
+ "extra_flags": {
34
+ "-k": "Keep listening after client disconnects (accept multiple connections)",
35
+ "-e": "Execute a program after connection (not available in all versions)",
36
+ "-N": "Shutdown the network socket after EOF on stdin",
37
+ },
38
+ },
39
+
40
+ "ncat": {
41
+ "man_url": "https://man7.org/linux/man-pages/man1/ncat.1.html",
42
+ "use_cases": [
43
+ "Create an encrypted tunnel with ncat --ssl -l 4444 for secure ad-hoc communication",
44
+ "Set up a simple chat server with ncat -l --chat 8080 for team debugging sessions",
45
+ "Proxy connections through an HTTP proxy to reach internal services with --proxy",
46
+ "Serve a single file over HTTPS by combining --ssl with --exec",
47
+ ],
48
+ "gotchas": [
49
+ "ncat is part of the nmap package and may not be installed by default on minimal systems",
50
+ "The --ssl flag generates a temporary certificate; clients will see certificate warnings unless you provide --ssl-cert and --ssl-key",
51
+ ],
52
+ "related": ["nc", "socat", "openssl", "nmap"],
53
+ "difficulty": "intermediate",
54
+ "extra_flags": {
55
+ "--ssl": "Use SSL/TLS encryption on the connection",
56
+ "--ssl-verify": "Require and verify the server certificate",
57
+ "-k": "Accept multiple connections in listen mode",
58
+ "--broker": "Enable connection brokering between multiple clients",
59
+ "--chat": "Start a simple chat server",
60
+ "-m": "Maximum number of simultaneous connections",
61
+ },
62
+ },
63
+
64
+ "netcat": {
65
+ "man_url": "https://man7.org/linux/man-pages/man1/ncat.1.html",
66
+ "use_cases": [
67
+ "Quick port scan of common ports with nc -zv host 20-100",
68
+ "Test SMTP server connectivity by connecting to port 25 and typing HELO commands",
69
+ "Banner grab a service to identify its version: echo '' | nc -w3 host 22",
70
+ ],
71
+ "gotchas": [
72
+ "The netcat command may point to different implementations depending on your distro -- check which version with nc -h or readlink $(which nc)",
73
+ "Port scanning with -z is slow compared to nmap; use nmap for serious scanning work",
74
+ ],
75
+ "related": ["nc", "ncat", "socat", "nmap"],
76
+ "difficulty": "intermediate",
77
+ "extra_flags": {},
78
+ },
79
+
80
+ "socat": {
81
+ "man_url": "https://man7.org/linux/man-pages/man1/socat.1.html",
82
+ "use_cases": [
83
+ "Forward a local TCP port to a remote host: socat TCP-LISTEN:8080,fork TCP:remote:80",
84
+ "Create an SSL-encrypted tunnel: socat TCP-LISTEN:443,fork,reuseaddr OPENSSL:target:443",
85
+ "Bridge a Unix socket to a TCP port for remote access to Docker or database sockets",
86
+ "Connect two different socket types, like converting a serial port to a TCP stream",
87
+ ],
88
+ "gotchas": [
89
+ "socat address syntax is powerful but complex -- the learning curve is steep compared to netcat",
90
+ "Forgetting the fork option on a listener means it handles only one connection then exits",
91
+ "The reuseaddr option is often needed to avoid 'address already in use' errors on quick restarts",
92
+ ],
93
+ "related": ["nc", "ncat", "ssh", "openssl"],
94
+ "difficulty": "advanced",
95
+ "extra_flags": {
96
+ "-4": "Use IPv4 only",
97
+ "-6": "Use IPv6 only",
98
+ "-t": "Set EOF timeout in seconds",
99
+ "-T": "Set total inactivity timeout in seconds",
100
+ "-b": "Set data transfer block size (default 8192)",
101
+ },
102
+ },
103
+
104
+ "telnet": {
105
+ "man_url": "https://man7.org/linux/man-pages/man1/telnet.1.html",
106
+ "use_cases": [
107
+ "Test if a web server is responding: telnet host 80 then type GET / HTTP/1.0",
108
+ "Debug SMTP mail delivery by connecting to port 25 and issuing EHLO, MAIL FROM, RCPT TO commands",
109
+ "Verify a Redis server is accessible: telnet host 6379 then type PING",
110
+ "Check if a specific port is reachable through a firewall when nc is not installed",
111
+ ],
112
+ "gotchas": [
113
+ "telnet transmits everything including passwords in plain text -- never use it for actual remote login; use SSH instead",
114
+ "telnet is not installed by default on many modern distributions; you may need to install it explicitly",
115
+ "The escape character (default Ctrl-]) is needed to close a telnet session; just closing the terminal may leave the connection open",
116
+ ],
117
+ "related": ["ssh", "nc", "curl", "openssl"],
118
+ "difficulty": "beginner",
119
+ "extra_flags": {},
120
+ },
121
+
122
+ "ftp": {
123
+ "man_url": "https://man7.org/linux/man-pages/man1/ftp.1.html",
124
+ "use_cases": [
125
+ "Upload files to a legacy web hosting provider that only supports FTP",
126
+ "Automate file transfers from an FTP server using a script with -n and heredoc commands",
127
+ "Download firmware updates from embedded device FTP servers during maintenance windows",
128
+ ],
129
+ "gotchas": [
130
+ "FTP transmits credentials and data in plain text -- use sftp or scp for anything involving sensitive data",
131
+ "Active mode FTP requires the server to connect back to your machine, which fails behind most NAT/firewalls; use -p for passive mode",
132
+ "Binary mode must be set explicitly with 'binary' command before transferring non-text files, or they will be corrupted",
133
+ ],
134
+ "related": ["sftp", "scp", "rsync", "curl"],
135
+ "difficulty": "beginner",
136
+ "extra_flags": {},
137
+ },
138
+
139
+ "tftp": {
140
+ "man_url": "https://man7.org/linux/man-pages/man1/tftp.1.html",
141
+ "use_cases": [
142
+ "Network boot (PXE) servers use TFTP to deliver boot images to diskless clients",
143
+ "Push firmware updates to network switches and routers that support TFTP",
144
+ "Transfer configuration files to embedded devices with minimal network stacks",
145
+ ],
146
+ "gotchas": [
147
+ "TFTP has no authentication whatsoever -- anyone on the network can read or write files if the server allows it",
148
+ "TFTP uses UDP port 69 and has a maximum file size of 32MB in the original protocol (extensions exist but are not universal)",
149
+ "The TFTP server directory must be pre-configured; you cannot browse or list files like FTP",
150
+ ],
151
+ "related": ["ftp", "scp", "curl"],
152
+ "difficulty": "intermediate",
153
+ "extra_flags": {},
154
+ },
155
+
156
+ "traceroute": {
157
+ "man_url": "https://man7.org/linux/man-pages/man8/traceroute.8.html",
158
+ "use_cases": [
159
+ "Diagnose where a network path fails when you cannot reach a remote server",
160
+ "Identify which ISP or network segment is causing high latency",
161
+ "Verify that traffic is taking the expected route through your network infrastructure",
162
+ ],
163
+ "gotchas": [
164
+ "Many routers and firewalls block or rate-limit traceroute probes, showing * * * for those hops -- this does not always mean the hop is down",
165
+ "Default UDP-based traceroute may be blocked where ICMP (-I) is allowed, or vice versa; try both methods",
166
+ "traceroute requires root privileges for ICMP mode (-I); use tracepath as a non-root alternative",
167
+ ],
168
+ "related": ["tracepath", "mtr", "ping", "ip"],
169
+ "difficulty": "intermediate",
170
+ "extra_flags": {
171
+ "-T": "Use TCP SYN probes instead of UDP (useful when UDP is firewalled)",
172
+ "-p": "Set the destination port for UDP probes",
173
+ "-q": "Set the number of probe packets per hop (default 3)",
174
+ },
175
+ },
176
+
177
+ "tracepath": {
178
+ "man_url": "https://man7.org/linux/man-pages/man8/tracepath.8.html",
179
+ "use_cases": [
180
+ "Trace a network path without root privileges when traceroute is not available",
181
+ "Discover the Path MTU to a destination to diagnose packet fragmentation issues",
182
+ "Quick network path diagnosis on servers where you do not have sudo access",
183
+ ],
184
+ "gotchas": [
185
+ "tracepath does not support all the protocol options that traceroute has (no TCP mode, no ICMP mode)",
186
+ "Path MTU discovery may report incorrect values if ICMP 'need fragmentation' messages are blocked by intermediate firewalls",
187
+ ],
188
+ "related": ["traceroute", "mtr", "ping"],
189
+ "difficulty": "beginner",
190
+ "extra_flags": {},
191
+ },
192
+
193
+ "mtr": {
194
+ "man_url": "https://linux.die.net/man/8/mtr",
195
+ "use_cases": [
196
+ "Diagnose intermittent packet loss at a specific network hop that one-shot traceroute misses",
197
+ "Generate a network quality report for an ISP support ticket with mtr -r -c 100 host",
198
+ "Monitor real-time latency to a game server or VoIP endpoint to correlate with quality drops",
199
+ "Test if a firewall is blocking TCP traffic with mtr -T -P 443 host",
200
+ ],
201
+ "gotchas": [
202
+ "Packet loss shown at intermediate hops does not always indicate a problem -- many routers deprioritize ICMP responses causing false loss readings",
203
+ "mtr requires root privileges for raw socket access; some distributions provide a setuid wrapper",
204
+ "The -r report mode sends 10 cycles by default, which may not be enough to catch intermittent issues; use -c 100 or more",
205
+ ],
206
+ "related": ["traceroute", "tracepath", "ping"],
207
+ "difficulty": "intermediate",
208
+ "extra_flags": {
209
+ "-4": "Use IPv4 only",
210
+ "-6": "Use IPv6 only",
211
+ "-s": "Set the packet size in bytes",
212
+ "-i": "Set the interval between ICMP ECHO requests",
213
+ "-e": "Display MPLS information in report mode",
214
+ },
215
+ },
216
+
217
+ "dig": {
218
+ "man_url": "https://linux.die.net/man/1/dig",
219
+ "use_cases": [
220
+ "Verify DNS propagation after changing A records: dig @8.8.8.8 example.com A +short",
221
+ "Debug email delivery by checking MX records: dig -t MX example.com",
222
+ "Trace the full DNS delegation chain to find where resolution breaks: dig example.com +trace",
223
+ "Check DNSSEC validation: dig example.com +dnssec",
224
+ "Look up TXT records for SPF/DKIM verification: dig -t TXT example.com",
225
+ ],
226
+ "gotchas": [
227
+ "dig queries your system's default DNS resolver unless you specify one with @server -- results may differ from what the public sees",
228
+ "The +short flag strips all context; when debugging, use the full output to check TTL, authority section, and response flags",
229
+ "dig is part of the bind-utils or dnsutils package and may not be installed on minimal systems; use host as a simpler fallback",
230
+ ],
231
+ "related": ["nslookup", "host", "whois"],
232
+ "difficulty": "intermediate",
233
+ "extra_flags": {
234
+ "+noall +answer": "Show only the answer section for clean output",
235
+ "+dnssec": "Request DNSSEC records",
236
+ "+tcp": "Use TCP instead of UDP for the query",
237
+ "-x": "Perform a reverse DNS lookup on an IP address",
238
+ },
239
+ },
240
+
241
+ "nslookup": {
242
+ "man_url": "https://linux.die.net/man/1/nslookup",
243
+ "use_cases": [
244
+ "Quick hostname-to-IP resolution check: nslookup example.com",
245
+ "Query a specific DNS server to test if it has updated records: nslookup example.com 8.8.8.8",
246
+ "Look up MX records for email troubleshooting: nslookup -type=MX example.com",
247
+ ],
248
+ "gotchas": [
249
+ "nslookup is considered deprecated by the ISC (BIND authors) in favor of dig; it may give misleading results in some edge cases",
250
+ "nslookup bypasses the system resolver's /etc/hosts file, so local hostname overrides will not appear",
251
+ "Interactive mode can be confusing -- type 'exit' to quit, not Ctrl-C which just cancels the current query",
252
+ ],
253
+ "related": ["dig", "host", "whois"],
254
+ "difficulty": "beginner",
255
+ "extra_flags": {},
256
+ },
257
+
258
+ "host": {
259
+ "man_url": "https://man7.org/linux/man-pages/man1/host.1.html",
260
+ "use_cases": [
261
+ "Quick DNS lookup with clean output: host example.com",
262
+ "Reverse DNS lookup to find hostname for an IP: host 8.8.8.8",
263
+ "Check all record types for a domain: host -a example.com",
264
+ ],
265
+ "gotchas": [
266
+ "host output format varies between versions; scripts should use dig +short for reliable parsing",
267
+ "Like dig, host bypasses /etc/hosts and queries DNS servers directly",
268
+ ],
269
+ "related": ["dig", "nslookup", "whois"],
270
+ "difficulty": "beginner",
271
+ "extra_flags": {},
272
+ },
273
+
274
+ "ip": {
275
+ "man_url": "https://man7.org/linux/man-pages/man8/ip.8.html",
276
+ "use_cases": [
277
+ "View all IP addresses assigned to interfaces: ip -br addr (brief, readable format)",
278
+ "Add a static route: ip route add 10.0.0.0/8 via 192.168.1.1",
279
+ "Bring a network interface up or down: ip link set eth0 up/down",
280
+ "View the ARP neighbor cache: ip neigh show",
281
+ "Add a secondary IP address to an interface: ip addr add 192.168.1.100/24 dev eth0",
282
+ ],
283
+ "gotchas": [
284
+ "Changes made with ip are not persistent across reboots -- use netplan, NetworkManager, or /etc/network/interfaces for permanent config",
285
+ "ip replaces ifconfig, route, and arp but uses different syntax for everything; old muscle memory does not transfer",
286
+ "The ip command requires the iproute2 package, which is standard on modern distros but may be missing on very minimal containers",
287
+ ],
288
+ "related": ["ifconfig", "route", "arp", "ss", "netstat"],
289
+ "difficulty": "intermediate",
290
+ "extra_flags": {
291
+ "-s": "Show statistics (packet counts, errors)",
292
+ "-j": "Output in JSON format for scripting",
293
+ "-4": "Show only IPv4",
294
+ "-6": "Show only IPv6",
295
+ },
296
+ },
297
+
298
+ "ifconfig": {
299
+ "man_url": "https://man7.org/linux/man-pages/man8/ifconfig.8.html",
300
+ "use_cases": [
301
+ "Quick check of your IP address: ifconfig (or ifconfig eth0 for a specific interface)",
302
+ "Temporarily assign an IP address: ifconfig eth0 192.168.1.100 netmask 255.255.255.0",
303
+ "Bring an interface up or down: ifconfig eth0 up / ifconfig eth0 down",
304
+ ],
305
+ "gotchas": [
306
+ "ifconfig is deprecated in favor of the ip command on modern Linux systems -- it may not be installed by default",
307
+ "ifconfig cannot display or manage multiple IP addresses per interface properly; ip addr handles this correctly",
308
+ "On many modern distros, ifconfig is in /sbin which may not be in a regular user's PATH",
309
+ ],
310
+ "related": ["ip", "route", "netstat"],
311
+ "difficulty": "beginner",
312
+ "extra_flags": {
313
+ "-a": "Display all interfaces including those that are down",
314
+ "-s": "Display a short summary list",
315
+ },
316
+ },
317
+
318
+ "route": {
319
+ "man_url": "https://man7.org/linux/man-pages/man8/route.8.html",
320
+ "use_cases": [
321
+ "View the kernel routing table: route -n",
322
+ "Add a default gateway: route add default gw 192.168.1.1",
323
+ "Add a route to a specific network: route add -net 10.0.0.0/8 gw 192.168.1.254",
324
+ ],
325
+ "gotchas": [
326
+ "route is deprecated; use ip route on modern systems for full functionality",
327
+ "Routes added with route are not persistent -- they disappear on reboot unless added to startup scripts",
328
+ "Forgetting -n causes slow output because route tries to reverse-DNS every address",
329
+ ],
330
+ "related": ["ip", "netstat", "traceroute"],
331
+ "difficulty": "intermediate",
332
+ "extra_flags": {},
333
+ },
334
+
335
+ "netstat": {
336
+ "man_url": "https://man7.org/linux/man-pages/man8/netstat.8.html",
337
+ "use_cases": [
338
+ "Find which process is using port 8080: netstat -tlnp | grep 8080",
339
+ "Show all established TCP connections: netstat -tn",
340
+ "List all listening services: netstat -tlnp",
341
+ ],
342
+ "gotchas": [
343
+ "netstat is deprecated in favor of ss, which is faster and provides more information",
344
+ "The -p flag requires root privileges to see process names for all sockets, not just your own",
345
+ "netstat may not be installed by default on modern systems; install the net-tools package",
346
+ ],
347
+ "related": ["ss", "lsof", "ip"],
348
+ "difficulty": "intermediate",
349
+ "extra_flags": {
350
+ "-a": "Show all sockets including listening and non-listening",
351
+ "-r": "Display the kernel routing table",
352
+ "-s": "Display summary statistics per protocol",
353
+ "-c": "Continuously refresh the display",
354
+ },
355
+ },
356
+
357
+ "ss": {
358
+ "man_url": "https://man7.org/linux/man-pages/man8/ss.8.html",
359
+ "use_cases": [
360
+ "Find which process is listening on port 3000: ss -tlnp | grep 3000",
361
+ "Show all established connections with process info: ss -tnp",
362
+ "Display socket memory usage to debug buffer bloat: ss -tm",
363
+ "Filter connections by state: ss state established '( dport = :443 )'",
364
+ "Display summary statistics for all protocols: ss -s",
365
+ ],
366
+ "gotchas": [
367
+ "The -p flag requires root to show processes for sockets owned by other users",
368
+ "ss filter expressions use a different syntax than netstat grep patterns -- read the man page for the state and address filter syntax",
369
+ "ss output columns differ from netstat; scripts that parse netstat output need rewriting",
370
+ ],
371
+ "related": ["netstat", "lsof", "ip"],
372
+ "difficulty": "intermediate",
373
+ "extra_flags": {
374
+ "-a": "Show both listening and non-listening sockets",
375
+ "-s": "Print summary statistics",
376
+ "-o": "Show timer information",
377
+ "-e": "Show detailed socket information (uid, inode)",
378
+ "-m": "Show socket memory usage",
379
+ "-i": "Show internal TCP information (congestion, RTT)",
380
+ "-K": "Forcibly close a socket",
381
+ "-H": "Suppress header line",
382
+ },
383
+ },
384
+
385
+ "arp": {
386
+ "man_url": "https://man7.org/linux/man-pages/man8/arp.8.html",
387
+ "use_cases": [
388
+ "View the ARP cache to see MAC-to-IP mappings on the local network: arp -a",
389
+ "Set a static ARP entry to prevent ARP spoofing for a critical gateway",
390
+ "Diagnose duplicate IP addresses by checking for multiple MAC addresses",
391
+ ],
392
+ "gotchas": [
393
+ "arp is deprecated; use ip neigh on modern systems",
394
+ "The ARP cache has timeouts, so entries may disappear if not recently used",
395
+ "Static ARP entries do not survive reboots unless configured in startup scripts",
396
+ ],
397
+ "related": ["arping", "ip", "ifconfig"],
398
+ "difficulty": "intermediate",
399
+ "extra_flags": {},
400
+ },
401
+
402
+ "arping": {
403
+ "man_url": "https://man7.org/linux/man-pages/man8/arping.8.html",
404
+ "use_cases": [
405
+ "Test layer-2 connectivity when ICMP ping is blocked by a firewall",
406
+ "Detect duplicate IP addresses on a network with arping -D",
407
+ "Discover the MAC address of a host on the local network",
408
+ ],
409
+ "gotchas": [
410
+ "arping only works on the local network segment -- it cannot cross routers",
411
+ "Requires root privileges to send raw ARP packets",
412
+ "There are two different arping implementations (Thomas Habets and iputils) with slightly different flags",
413
+ ],
414
+ "related": ["arp", "ping", "ip"],
415
+ "difficulty": "intermediate",
416
+ "extra_flags": {},
417
+ },
418
+
419
+ "iptables": {
420
+ "man_url": "https://man7.org/linux/man-pages/man8/iptables.8.html",
421
+ "use_cases": [
422
+ "Block an abusive IP: iptables -A INPUT -s 1.2.3.4 -j DROP",
423
+ "Allow inbound HTTP/HTTPS: iptables -A INPUT -p tcp --dport 80 -j ACCEPT",
424
+ "Set up port forwarding (NAT): iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080",
425
+ "Log dropped packets for debugging: iptables -A INPUT -j LOG --log-prefix 'DROPPED: '",
426
+ "Save rules to survive reboot: iptables-save > /etc/iptables/rules.v4",
427
+ ],
428
+ "gotchas": [
429
+ "Rules are evaluated in order and first match wins -- a broad ACCEPT at the top can override specific DROP rules below it",
430
+ "iptables rules are lost on reboot unless saved with iptables-save and restored with iptables-restore or a service like netfilter-persistent",
431
+ "Flushing rules with -F on a remote server with default DROP policy will lock you out -- always set -P INPUT ACCEPT before flushing",
432
+ "iptables is being replaced by nftables on newer distributions; new deployments should prefer nft",
433
+ ],
434
+ "related": ["nft", "ufw", "firewall-cmd", "ip"],
435
+ "difficulty": "advanced",
436
+ "extra_flags": {
437
+ "-t": "Specify table (filter, nat, mangle, raw, security)",
438
+ "-s": "Source IP address or range",
439
+ "-d": "Destination IP address or range",
440
+ "-j": "Target action (ACCEPT, DROP, REJECT, LOG)",
441
+ "-p": "Protocol (tcp, udp, icmp)",
442
+ "--dport": "Destination port (requires -p tcp or -p udp)",
443
+ "--sport": "Source port (requires -p tcp or -p udp)",
444
+ "-i": "Input network interface",
445
+ "-o": "Output network interface",
446
+ },
447
+ },
448
+
449
+ "nft": {
450
+ "man_url": "https://www.netfilter.org/projects/nftables/manpage.html",
451
+ "use_cases": [
452
+ "List the entire active ruleset: nft list ruleset",
453
+ "Create a basic firewall accepting established connections and dropping others",
454
+ "Replace complex iptables + ip6tables rules with a single unified nft ruleset",
455
+ "Load a firewall configuration from a file: nft -f /etc/nftables.conf",
456
+ ],
457
+ "gotchas": [
458
+ "nftables uses a different syntax from iptables; existing iptables rules cannot be pasted directly",
459
+ "The iptables-translate tool can help convert iptables rules to nft syntax",
460
+ "nft requires root privileges for all operations",
461
+ "Flushing the ruleset on a remote server will lock you out if the default policy is drop",
462
+ ],
463
+ "related": ["iptables", "ufw", "firewall-cmd"],
464
+ "difficulty": "advanced",
465
+ "extra_flags": {
466
+ "-j": "Output in JSON format for programmatic use",
467
+ "-s": "Translate numeric protocols and services to names",
468
+ "-c": "Check command validity without applying changes",
469
+ },
470
+ },
471
+
472
+ "ufw": {
473
+ "man_url": "https://manpages.ubuntu.com/manpages/man8/ufw.8.html",
474
+ "use_cases": [
475
+ "Set up a basic server firewall: ufw default deny incoming, ufw allow ssh, ufw allow 80/tcp, ufw enable",
476
+ "Allow connections only from a specific IP: ufw allow from 10.0.0.5 to any port 22",
477
+ "Rate limit SSH to prevent brute force: ufw limit ssh",
478
+ "Check firewall status and rules: ufw status verbose",
479
+ ],
480
+ "gotchas": [
481
+ "Enabling ufw on a remote server without first allowing SSH will lock you out immediately",
482
+ "ufw operates on top of iptables/nftables; direct iptables rules may conflict with ufw rules",
483
+ "ufw does not manage Docker's iptables rules -- Docker bypasses ufw by inserting its own chains",
484
+ ],
485
+ "related": ["iptables", "nft", "firewall-cmd"],
486
+ "difficulty": "beginner",
487
+ "extra_flags": {
488
+ "limit": "Rate limit connections to a port (6 connections in 30 seconds)",
489
+ "logging": "Set logging level (off, low, medium, high, full)",
490
+ "status numbered": "Show rules with numbers for easy deletion",
491
+ },
492
+ },
493
+
494
+ "firewall-cmd": {
495
+ "man_url": "https://firewalld.org/documentation/man-pages/firewall-cmd.html",
496
+ "use_cases": [
497
+ "Open HTTP permanently: firewall-cmd --add-service=http --permanent && firewall-cmd --reload",
498
+ "List all allowed services and ports: firewall-cmd --list-all",
499
+ "Temporarily open a port for testing (removed on reload): firewall-cmd --add-port=8080/tcp",
500
+ "Add a rich rule for IP-based access control: firewall-cmd --add-rich-rule='rule family=ipv4 source address=10.0.0.0/24 accept' --permanent",
501
+ ],
502
+ "gotchas": [
503
+ "Changes without --permanent are lost on firewalld restart or reload",
504
+ "After adding --permanent rules, you must --reload for them to take effect immediately",
505
+ "firewall-cmd is specific to RHEL/CentOS/Fedora; Debian/Ubuntu systems use ufw instead",
506
+ ],
507
+ "related": ["iptables", "ufw", "nft"],
508
+ "difficulty": "intermediate",
509
+ "extra_flags": {
510
+ "--get-active-zones": "Show which zones are active and their interfaces",
511
+ "--get-default-zone": "Show the default zone",
512
+ "--set-default-zone": "Change the default zone",
513
+ "--add-rich-rule": "Add a complex rule with source/destination filtering",
514
+ },
515
+ },
516
+
517
+ "tcpdump": {
518
+ "man_url": "https://man7.org/linux/man-pages/man8/tcpdump.8.html",
519
+ "use_cases": [
520
+ "Capture HTTP traffic on all interfaces: tcpdump -i any port 80 -A",
521
+ "Save a capture for later analysis in Wireshark: tcpdump -i eth0 -w capture.pcap",
522
+ "Debug DNS resolution issues: tcpdump -i any port 53 -n",
523
+ "Monitor traffic to/from a specific host: tcpdump -i any host 10.0.0.5 -n",
524
+ "Capture only SYN packets to see new connections: tcpdump 'tcp[tcpflags] & tcp-syn != 0'",
525
+ ],
526
+ "gotchas": [
527
+ "tcpdump requires root privileges for packet capture",
528
+ "Capturing on a busy interface without filters generates enormous output -- always use BPF filters to narrow scope",
529
+ "On a server with many connections, -n (no name resolution) is essential to avoid slow output caused by reverse DNS lookups",
530
+ "The -c flag is important in scripts to avoid capturing indefinitely",
531
+ ],
532
+ "related": ["wireshark", "nmap", "ss", "iptables"],
533
+ "difficulty": "advanced",
534
+ "extra_flags": {
535
+ "-s": "Set the snapshot length (bytes to capture per packet; 0 = full packet)",
536
+ "-e": "Print link-layer (MAC) headers",
537
+ "-D": "List available network interfaces for capture",
538
+ "-l": "Line-buffer stdout for real-time piping to grep",
539
+ "-G": "Rotate capture file every N seconds",
540
+ },
541
+ },
542
+
543
+ "wireshark": {
544
+ "man_url": "https://www.wireshark.org/docs/man-pages/wireshark.html",
545
+ "use_cases": [
546
+ "Analyze a pcap file captured with tcpdump to visually inspect protocol conversations",
547
+ "Debug TLS handshake failures by examining the Certificate and ServerHello messages",
548
+ "Filter and follow a specific TCP stream to reconstruct an HTTP conversation",
549
+ "Identify network performance issues using the IO graphs and expert information features",
550
+ ],
551
+ "gotchas": [
552
+ "Wireshark's GUI requires a display server (X11/Wayland); use tshark for CLI-based analysis on headless servers",
553
+ "Capturing on a busy network generates massive pcap files quickly -- use capture filters (BPF) to reduce volume",
554
+ "Display filters (applied after capture) use different syntax from capture filters (BPF syntax applied during capture)",
555
+ ],
556
+ "related": ["tcpdump", "nmap", "ss"],
557
+ "difficulty": "advanced",
558
+ "extra_flags": {
559
+ "-T": "Set output format for tshark (fields, json, pdml)",
560
+ },
561
+ },
562
+
563
+ "nmap": {
564
+ "man_url": "https://nmap.org/book/man.html",
565
+ "use_cases": [
566
+ "Scan a subnet to discover live hosts: nmap -sn 192.168.1.0/24",
567
+ "Full port scan with service version detection: nmap -sV -p- host",
568
+ "Check if a specific port is open: nmap -p 443 host",
569
+ "Detect the operating system of a remote host: nmap -O host",
570
+ "Run vulnerability scanning scripts: nmap --script vuln host",
571
+ ],
572
+ "gotchas": [
573
+ "Port scanning networks you do not own or have permission to scan is illegal in many jurisdictions",
574
+ "A full port scan (-p-) of 65535 ports is slow; SYN scan (-sS) is faster but requires root",
575
+ "Aggressive scans (-A) are noisy and easily detected by intrusion detection systems",
576
+ "nmap's default scan only covers the top 1000 ports, not all 65535",
577
+ ],
578
+ "related": ["masscan", "nc", "ss", "tcpdump"],
579
+ "difficulty": "advanced",
580
+ "extra_flags": {
581
+ "-sn": "Ping scan only (host discovery, no port scan)",
582
+ "-sU": "UDP port scan (much slower than TCP)",
583
+ "--script": "Run NSE scripts for vulnerability detection",
584
+ "-T": "Set timing template (0-5, higher is faster/noisier)",
585
+ "-oA": "Output in all formats (normal, XML, grepable)",
586
+ },
587
+ },
588
+
589
+ "masscan": {
590
+ "man_url": "https://github.com/robertdavidgraham/masscan",
591
+ "use_cases": [
592
+ "Rapidly scan a large IP range for specific open ports: masscan 10.0.0.0/8 -p80,443 --rate=50000",
593
+ "Discover all web servers on a /16 network in minutes",
594
+ "Feed masscan results into nmap for detailed follow-up scanning of discovered hosts",
595
+ ],
596
+ "gotchas": [
597
+ "High scan rates can overwhelm networks, trigger IDS alerts, and crash fragile devices -- start with conservative rates",
598
+ "masscan uses its own TCP stack and does not go through the OS, so firewall rules on the scanning host are bypassed",
599
+ "Results are less accurate than nmap for individual hosts due to the asynchronous scanning approach",
600
+ "Requires root for raw socket access",
601
+ ],
602
+ "related": ["nmap", "nc", "tcpdump"],
603
+ "difficulty": "advanced",
604
+ "extra_flags": {},
605
+ },
606
+
607
+ "nikto": {
608
+ "man_url": "https://github.com/sullo/nikto/wiki",
609
+ "use_cases": [
610
+ "Quick web server security audit: nikto -h http://target.com",
611
+ "Scan an HTTPS site: nikto -h target.com -p 443 -ssl",
612
+ "Generate an HTML report for a security assessment: nikto -h target -o report.html -Format htm",
613
+ ],
614
+ "gotchas": [
615
+ "Nikto is extremely noisy and generates hundreds of requests -- it will be detected by any WAF or IDS",
616
+ "Only scan systems you have explicit authorization to test",
617
+ "Nikto checks for known vulnerabilities and misconfigurations; it does not find custom application bugs",
618
+ "Results include many false positives; manual verification is always required",
619
+ ],
620
+ "related": ["nmap", "curl", "openssl"],
621
+ "difficulty": "advanced",
622
+ "extra_flags": {},
623
+ },
624
+
625
+ "whois": {
626
+ "man_url": "https://man7.org/linux/man-pages/man1/whois.1.html",
627
+ "use_cases": [
628
+ "Find out who owns a domain: whois example.com",
629
+ "Check domain expiration date before it lapses",
630
+ "Look up the organization responsible for an IP address: whois 8.8.8.8",
631
+ "Determine the registrar and nameservers for a domain",
632
+ ],
633
+ "gotchas": [
634
+ "Many domain registrars now use privacy protection services that hide the real owner information",
635
+ "WHOIS rate limiting may block you if you run too many queries in succession",
636
+ "The output format varies significantly between different TLD registries",
637
+ ],
638
+ "related": ["dig", "nslookup", "host"],
639
+ "difficulty": "beginner",
640
+ "extra_flags": {},
641
+ },
642
+
643
+ "openssl": {
644
+ "man_url": "https://www.openssl.org/docs/man3.0/man1/",
645
+ "use_cases": [
646
+ "Test an HTTPS connection and view the certificate chain: openssl s_client -connect host:443",
647
+ "Generate a self-signed certificate for development: openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes",
648
+ "Check certificate expiration: openssl x509 -in cert.pem -noout -enddate",
649
+ "Create a CSR for a production certificate: openssl req -new -key server.key -out server.csr",
650
+ "Generate a random password: openssl rand -base64 32",
651
+ ],
652
+ "gotchas": [
653
+ "The -nodes flag means 'no DES encryption' on the private key, not 'no des' -- it stores the key unencrypted which is a security risk in production",
654
+ "openssl s_client does not verify certificates by default; add -verify_return_error to catch invalid certs",
655
+ "OpenSSL 1.x and 3.x have different default behaviors and deprecated algorithms; check your version with openssl version",
656
+ ],
657
+ "related": ["certbot", "ssh", "curl"],
658
+ "difficulty": "advanced",
659
+ "extra_flags": {
660
+ "rand": "Generate random bytes",
661
+ "speed": "Benchmark cryptographic algorithms",
662
+ "verify": "Verify a certificate chain",
663
+ "pkcs12": "Convert between PFX/PKCS12 and PEM formats",
664
+ },
665
+ },
666
+
667
+ "certbot": {
668
+ "man_url": "https://certbot.eff.org/docs/",
669
+ "use_cases": [
670
+ "Get a free HTTPS certificate for Nginx: certbot --nginx -d example.com -d www.example.com",
671
+ "Obtain a certificate without modifying your web server: certbot certonly --standalone -d example.com",
672
+ "Set up automatic certificate renewal: certbot renew (usually in a cron job or systemd timer)",
673
+ "Test the renewal process without actually renewing: certbot renew --dry-run",
674
+ ],
675
+ "gotchas": [
676
+ "Certbot needs port 80 (HTTP) or 443 (HTTPS) accessible from the internet for domain validation",
677
+ "Let's Encrypt certificates are only valid for 90 days -- automated renewal is essential",
678
+ "Rate limits apply: 50 certificates per registered domain per week; use --staging for testing",
679
+ "The standalone mode requires stopping your web server temporarily; use --webroot or --nginx/--apache to avoid downtime",
680
+ ],
681
+ "related": ["openssl", "nginx", "apache"],
682
+ "difficulty": "intermediate",
683
+ "extra_flags": {
684
+ "--agree-tos": "Agree to the terms of service non-interactively",
685
+ "--email": "Set the registration email for expiry notifications",
686
+ "--non-interactive": "Run without any user interaction",
687
+ "certificates": "List all managed certificates and their expiry dates",
688
+ "revoke": "Revoke a certificate",
689
+ },
690
+ },
691
+
692
+ "http": {
693
+ "man_url": "https://httpie.io/docs/cli",
694
+ "use_cases": [
695
+ "Quick API testing with readable output: http GET https://api.example.com/users",
696
+ "POST JSON data intuitively: http POST api.example.com/items name=widget price:=9.99",
697
+ "Download a file: http --download https://example.com/file.zip",
698
+ "Debug HTTP by printing full request and response: http --print=HhBb example.com",
699
+ ],
700
+ "gotchas": [
701
+ "HTTPie uses 'http' as the command name, which can conflict with other tools; the package name is 'httpie'",
702
+ "The := syntax sends raw JSON values (numbers, booleans); = sends strings -- mixing them up causes type errors in APIs",
703
+ "HTTPie follows redirects by default (unlike curl), which may hide redirect issues during debugging",
704
+ ],
705
+ "related": ["curl", "wget"],
706
+ "difficulty": "beginner",
707
+ "extra_flags": {
708
+ "--download": "Download the response body to a file",
709
+ "--session": "Create or reuse a named session with persistent headers/cookies",
710
+ "--timeout": "Set the request timeout in seconds",
711
+ },
712
+ },
713
+
714
+ "httpie": {
715
+ "man_url": "https://httpie.io/docs/cli",
716
+ "use_cases": [
717
+ "Test REST APIs with human-friendly output formatting and syntax highlighting",
718
+ "Submit forms: http --form POST example.com/login username=admin password=secret",
719
+ "Send authenticated requests: http --auth user:pass GET api.example.com/data",
720
+ ],
721
+ "gotchas": [
722
+ "httpie is the package name; the actual command is 'http' (or 'https' for HTTPS)",
723
+ "HTTPie 3.x changed some defaults from 2.x; check the changelog when upgrading",
724
+ ],
725
+ "related": ["curl", "wget", "http"],
726
+ "difficulty": "beginner",
727
+ "extra_flags": {},
728
+ },
729
+
730
+ "ping": {
731
+ "man_url": "https://man7.org/linux/man-pages/man8/ping.8.html",
732
+ "use_cases": [
733
+ "Test basic network connectivity to a host: ping -c 4 google.com",
734
+ "Continuously monitor a connection with timestamps: ping -D host",
735
+ "Test with a specific packet size to check MTU issues: ping -s 1472 host",
736
+ "Quick check if a host is alive in a script: ping -c 1 -W 2 host > /dev/null 2>&1 && echo up",
737
+ ],
738
+ "gotchas": [
739
+ "Many hosts and firewalls block ICMP, so a failed ping does not necessarily mean the host is down -- the service may still be reachable",
740
+ "On Linux, ping runs indefinitely by default; always use -c to limit count in scripts",
741
+ "Flood ping (-f) requires root and can saturate a network link -- use with extreme caution",
742
+ "ping results show round-trip time, not one-way latency; actual one-way delay is roughly half the RTT",
743
+ ],
744
+ "related": ["traceroute", "mtr", "arping"],
745
+ "difficulty": "beginner",
746
+ "extra_flags": {
747
+ "-w": "Deadline timeout: exit after N seconds regardless of packet count",
748
+ "-W": "Timeout waiting for each response in seconds",
749
+ "-s": "Set packet data size in bytes (default 56)",
750
+ "-t": "Set the IP time-to-live",
751
+ "-I": "Specify source interface or address",
752
+ "-f": "Flood ping (requires root, use carefully)",
753
+ "-q": "Quiet output; only show summary at the end",
754
+ "-D": "Print timestamps before each line",
755
+ },
756
+ },
757
+
758
+ "scp": {
759
+ "man_url": "https://man.openbsd.org/scp",
760
+ "use_cases": [
761
+ "Copy a file to a remote server: scp file.txt user@host:/remote/path/",
762
+ "Copy a directory recursively: scp -r project/ user@host:/deploy/",
763
+ "Copy between two remote hosts through your local machine: scp user1@host1:file user2@host2:/path/",
764
+ "Use a specific SSH key: scp -i ~/.ssh/deploy_key file.txt user@host:/path/",
765
+ ],
766
+ "gotchas": [
767
+ "scp is considered deprecated by OpenSSH in favor of sftp or rsync -- it has known limitations with filename handling",
768
+ "scp copies the entire file every time; rsync only transfers differences and is much faster for repeated transfers",
769
+ "The -P flag (uppercase) specifies the port, unlike ssh which uses -p (lowercase)",
770
+ "Wildcards in remote paths must be quoted to prevent local shell expansion: scp 'user@host:/path/*.log' .",
771
+ ],
772
+ "related": ["sftp", "rsync", "ssh"],
773
+ "difficulty": "beginner",
774
+ "extra_flags": {
775
+ "-C": "Enable compression during transfer",
776
+ "-l": "Limit bandwidth in Kbit/s",
777
+ "-3": "Copy between two remote hosts through the local machine",
778
+ "-o": "Pass SSH options (e.g., -o StrictHostKeyChecking=no)",
779
+ },
780
+ },
781
+
782
+ "sftp": {
783
+ "man_url": "https://man.openbsd.org/sftp",
784
+ "use_cases": [
785
+ "Interactive file transfer session with a remote server: sftp user@host",
786
+ "Batch transfer files from a script: sftp -b commands.txt user@host",
787
+ "Resume interrupted directory uploads with a combination of get -r / put -r",
788
+ "Browse remote files interactively when you are unsure of the exact path",
789
+ ],
790
+ "gotchas": [
791
+ "sftp is not FTP over SSL; it is a completely different protocol that runs over SSH",
792
+ "The -P flag (uppercase) sets the port, matching scp but different from ssh's lowercase -p",
793
+ "Tab completion works in interactive mode but may be slow on high-latency connections",
794
+ ],
795
+ "related": ["scp", "rsync", "ssh", "ftp"],
796
+ "difficulty": "beginner",
797
+ "extra_flags": {
798
+ "-C": "Enable compression",
799
+ "-l": "Limit bandwidth in Kbit/s",
800
+ "-o": "Pass SSH options",
801
+ },
802
+ },
803
+
804
+ # =========================================================================
805
+ # PROCESS & SYSTEM COMMANDS
806
+ # =========================================================================
807
+
808
+ "top": {
809
+ "man_url": "https://man7.org/linux/man-pages/man1/top.1.html",
810
+ "use_cases": [
811
+ "Monitor CPU and memory usage in real time to find resource-hungry processes",
812
+ "Find the process consuming the most CPU: run top then press P to sort by CPU",
813
+ "Script batch monitoring: top -b -n 1 | head -20 for a snapshot",
814
+ "Filter to a specific user's processes: top -u www-data",
815
+ ],
816
+ "gotchas": [
817
+ "The %CPU column in top shows per-core percentage, so a multithreaded process can show over 100%",
818
+ "Memory readings can be confusing: 'used' includes buffer/cache; check 'avail' for actual available memory",
819
+ "top's interactive keys (P, M, T for sorting, k for kill, 1 for per-CPU) are essential but undiscoverable without reading help (press h)",
820
+ ],
821
+ "related": ["htop", "btop", "ps", "kill"],
822
+ "difficulty": "beginner",
823
+ "extra_flags": {
824
+ "-d": "Set refresh interval in seconds",
825
+ "-p": "Monitor only specific PIDs",
826
+ "-H": "Show individual threads",
827
+ "-c": "Show full command line instead of just the command name",
828
+ "-o": "Sort by a specific field",
829
+ },
830
+ },
831
+
832
+ "htop": {
833
+ "man_url": "https://man7.org/linux/man-pages/man1/htop.1.html",
834
+ "use_cases": [
835
+ "Interactively browse and kill processes with a user-friendly color interface",
836
+ "View per-CPU core utilization bars to identify single-threaded bottlenecks",
837
+ "Filter processes by name with / and search incrementally",
838
+ "Show a process tree with F5 to understand parent-child relationships",
839
+ ],
840
+ "gotchas": [
841
+ "htop is not installed by default on most systems; you need to install it from your package manager",
842
+ "htop shows threads by default (unlike top), which can make the process count seem much higher than expected; press H to toggle",
843
+ "Memory bars include shared memory which can overcount total usage when summing process memory",
844
+ ],
845
+ "related": ["top", "btop", "atop", "ps"],
846
+ "difficulty": "beginner",
847
+ "extra_flags": {
848
+ "-d": "Set refresh delay in tenths of seconds",
849
+ "-p": "Monitor specific PIDs only",
850
+ "-s": "Sort by the specified column",
851
+ "-C": "Use monochrome mode",
852
+ },
853
+ },
854
+
855
+ "btop": {
856
+ "man_url": "https://github.com/aristocratos/btop",
857
+ "use_cases": [
858
+ "Monitor system resources with a polished dashboard showing CPU, memory, disk, and network simultaneously",
859
+ "Use process tree view to understand hierarchical process relationships",
860
+ "Quick visual triage of system performance issues with color-coded resource graphs",
861
+ ],
862
+ "gotchas": [
863
+ "btop requires a terminal with true color and UTF-8 support; use -lc flag on limited terminals",
864
+ "btop is newer and less commonly available in default repos than htop; may need manual installation",
865
+ ],
866
+ "related": ["htop", "top", "atop"],
867
+ "difficulty": "beginner",
868
+ "extra_flags": {},
869
+ },
870
+
871
+ "atop": {
872
+ "man_url": "https://man7.org/linux/man-pages/man1/atop.1.html",
873
+ "use_cases": [
874
+ "Investigate past performance issues by replaying historical logs: atop -r /var/log/atop/atop_20240115",
875
+ "Identify the process that caused a CPU spike last night by scrubbing through recorded data",
876
+ "Monitor disk I/O per process to find which application is thrashing storage",
877
+ ],
878
+ "gotchas": [
879
+ "atop writes to /var/log/atop by default; these log files can grow large and should be rotated",
880
+ "The atop daemon must be running to record historical data; install and enable the atop service",
881
+ "Use t and T keys to navigate forward/backward through time intervals when replaying logs",
882
+ ],
883
+ "related": ["top", "htop", "sar", "iostat"],
884
+ "difficulty": "intermediate",
885
+ "extra_flags": {},
886
+ },
887
+
888
+ "kill": {
889
+ "man_url": "https://man7.org/linux/man-pages/man1/kill.1.html",
890
+ "use_cases": [
891
+ "Gracefully stop a process with kill PID which sends SIGTERM and allows cleanup",
892
+ "Force-kill an unresponsive process with kill -9 PID when SIGTERM is ignored",
893
+ "Send a reload signal to a daemon with kill -HUP PID to reload configuration without restarting",
894
+ "Stop a process group: kill -TERM -PGID (negative PID targets the group)",
895
+ ],
896
+ "gotchas": [
897
+ "kill -9 should be a last resort because it prevents the process from cleaning up resources like temp files, database connections, and lock files",
898
+ "kill requires the PID, not the process name -- use pkill or killall to signal processes by name instead",
899
+ "Zombie processes cannot be killed because they are already dead; you need to kill or fix their parent process",
900
+ "Sending signals to PID 1 (init/systemd) has special behavior and should be avoided",
901
+ ],
902
+ "related": ["pkill", "killall", "ps", "pgrep"],
903
+ "difficulty": "beginner",
904
+ "extra_flags": {
905
+ "-L": "List signals in a table format with numbers",
906
+ "-s": "Specify signal by name (e.g., -s TERM)",
907
+ "--timeout": "Send follow-up signal after specified milliseconds if process survives",
908
+ },
909
+ },
910
+
911
+ "killall": {
912
+ "man_url": "https://man7.org/linux/man-pages/man1/killall.1.html",
913
+ "use_cases": [
914
+ "Kill all instances of a process by name: killall firefox",
915
+ "Gracefully stop all node processes: killall -TERM node",
916
+ "Force-kill all hung instances: killall -9 frozen-app",
917
+ ],
918
+ "gotchas": [
919
+ "On Solaris, killall kills ALL processes (not by name) -- this Linux-specific behavior does not transfer to other Unix systems",
920
+ "killall requires an exact process name match; use pkill -f for partial or command-line matching",
921
+ "Without -i, killall provides no confirmation before killing multiple matching processes",
922
+ ],
923
+ "related": ["kill", "pkill", "pgrep", "ps"],
924
+ "difficulty": "beginner",
925
+ "extra_flags": {
926
+ "-e": "Require exact match of very long names (over 15 characters)",
927
+ "-u": "Kill only processes owned by the specified user",
928
+ "-w": "Wait for all killed processes to die before returning",
929
+ "-r": "Interpret process name as an extended regular expression",
930
+ },
931
+ },
932
+
933
+ "pkill": {
934
+ "man_url": "https://man7.org/linux/man-pages/man1/pkill.1.html",
935
+ "use_cases": [
936
+ "Kill all processes matching a pattern: pkill -f 'node server.js'",
937
+ "Signal all processes of a specific user: pkill -u baduser",
938
+ "Send SIGHUP to reload all nginx workers: pkill -HUP nginx",
939
+ ],
940
+ "gotchas": [
941
+ "Without -f, pkill only matches against the process name (first 15 chars), not the full command line",
942
+ "pkill matches with regex, so special characters in patterns need escaping",
943
+ "pkill returns exit code 1 if no processes matched, which can cause script failures with set -e",
944
+ ],
945
+ "related": ["pgrep", "kill", "killall", "ps"],
946
+ "difficulty": "beginner",
947
+ "extra_flags": {
948
+ "-x": "Require an exact match of the process name",
949
+ "-u": "Match only processes running as the specified user",
950
+ "-t": "Match only processes on the specified terminal",
951
+ "-P": "Match only processes whose parent PID matches",
952
+ "-o": "Select only the oldest (longest-running) matching process",
953
+ "-n": "Select only the newest (most recently started) matching process",
954
+ },
955
+ },
956
+
957
+ "pgrep": {
958
+ "man_url": "https://man7.org/linux/man-pages/man1/pgrep.1.html",
959
+ "use_cases": [
960
+ "Find PIDs of all python processes: pgrep python",
961
+ "Check if a specific service is running: pgrep -x nginx && echo running",
962
+ "List processes with their names: pgrep -la node",
963
+ "Find processes belonging to a user: pgrep -u www-data",
964
+ ],
965
+ "gotchas": [
966
+ "pgrep returns exit code 1 when no match is found, which is useful for conditionals but can break set -e scripts",
967
+ "Without -f, pgrep only matches the first 15 characters of the process name",
968
+ "pgrep may match itself if your grep pattern appears in the pgrep command line; -x for exact match helps",
969
+ ],
970
+ "related": ["pkill", "ps", "kill"],
971
+ "difficulty": "beginner",
972
+ "extra_flags": {
973
+ "-a": "List PID and full command line of matching processes",
974
+ "-c": "Count matching processes instead of listing PIDs",
975
+ "-d": "Set the delimiter between PIDs (default newline)",
976
+ },
977
+ },
978
+
979
+ "nice": {
980
+ "man_url": "https://man7.org/linux/man-pages/man1/nice.1.html",
981
+ "use_cases": [
982
+ "Run a CPU-intensive build at low priority: nice -n 19 make -j8",
983
+ "Start a backup job without impacting interactive users: nice -n 15 rsync -a /data /backup",
984
+ "Run a high-priority system task (requires root): sudo nice -n -10 critical-task",
985
+ ],
986
+ "gotchas": [
987
+ "Only root can set negative nice values (higher priority); regular users can only lower their priority",
988
+ "Nice values range from -20 (highest priority) to 19 (lowest); the default adjustment is 10",
989
+ "nice affects CPU scheduling priority only, not I/O priority -- use ionice for disk I/O scheduling",
990
+ ],
991
+ "related": ["renice", "ionice", "cpulimit"],
992
+ "difficulty": "intermediate",
993
+ "extra_flags": {},
994
+ },
995
+
996
+ "renice": {
997
+ "man_url": "https://man7.org/linux/man-pages/man1/renice.1.html",
998
+ "use_cases": [
999
+ "Lower the priority of a runaway process: renice -n 19 -p 1234",
1000
+ "Reprioritize all processes by a specific user: renice -n 10 -u batchuser",
1001
+ "Increase priority of a critical running process (root only): sudo renice -n -5 -p 5678",
1002
+ ],
1003
+ "gotchas": [
1004
+ "Regular users can only increase nice values (lower priority), never decrease them",
1005
+ "renice changes the priority of already-running processes; use nice to start new processes at a given priority",
1006
+ ],
1007
+ "related": ["nice", "kill", "top"],
1008
+ "difficulty": "intermediate",
1009
+ "extra_flags": {},
1010
+ },
1011
+
1012
+ "nohup": {
1013
+ "man_url": "https://man7.org/linux/man-pages/man1/nohup.1.html",
1014
+ "use_cases": [
1015
+ "Start a long-running training job that survives SSH disconnection: nohup python train.py > train.log 2>&1 &",
1016
+ "Run a server process that persists after logout: nohup ./server &",
1017
+ "Launch a batch job on a remote machine before disconnecting: nohup ./process_data.sh &",
1018
+ ],
1019
+ "gotchas": [
1020
+ "nohup appends output to nohup.out by default, which can grow very large; always redirect stdout/stderr explicitly",
1021
+ "nohup only ignores SIGHUP; combining with & is required to actually background the process",
1022
+ "For interactive or complex scenarios, tmux/screen are better choices than nohup because you can reattach",
1023
+ ],
1024
+ "related": ["disown", "screen", "tmux", "bg"],
1025
+ "difficulty": "beginner",
1026
+ "extra_flags": {},
1027
+ },
1028
+
1029
+ "bg": {
1030
+ "man_url": "https://www.gnu.org/software/bash/manual/html_node/Job-Control-Builtins.html",
1031
+ "use_cases": [
1032
+ "Resume a suspended job in the background after pressing Ctrl+Z: bg %1",
1033
+ "Continue working in your terminal after accidentally starting a long command in the foreground",
1034
+ ],
1035
+ "gotchas": [
1036
+ "bg is a shell builtin and only works with jobs managed by the current shell session",
1037
+ "A backgrounded job that tries to read from the terminal will be stopped again with SIGTTIN",
1038
+ "bg without arguments resumes the most recently suspended job",
1039
+ ],
1040
+ "related": ["fg", "jobs", "disown", "nohup"],
1041
+ "difficulty": "beginner",
1042
+ "extra_flags": {},
1043
+ },
1044
+
1045
+ "fg": {
1046
+ "man_url": "https://www.gnu.org/software/bash/manual/html_node/Job-Control-Builtins.html",
1047
+ "use_cases": [
1048
+ "Bring a background process back to the foreground to interact with it: fg %1",
1049
+ "Return to a suspended editor session after checking something in the shell",
1050
+ ],
1051
+ "gotchas": [
1052
+ "fg without arguments brings the most recently backgrounded/suspended job to the foreground",
1053
+ "If the job has already exited, fg will report an error",
1054
+ ],
1055
+ "related": ["bg", "jobs", "disown"],
1056
+ "difficulty": "beginner",
1057
+ "extra_flags": {},
1058
+ },
1059
+
1060
+ "jobs": {
1061
+ "man_url": "https://www.gnu.org/software/bash/manual/html_node/Job-Control-Builtins.html",
1062
+ "use_cases": [
1063
+ "List all background and suspended jobs in the current shell: jobs -l",
1064
+ "Check if background processes are still running before logging out",
1065
+ "Get the PID of a backgrounded job for use with kill: jobs -p",
1066
+ ],
1067
+ "gotchas": [
1068
+ "jobs only shows processes started from the current shell session; it cannot see processes from other terminals",
1069
+ "Job numbers (%1, %2) are different from PIDs and are local to the shell session",
1070
+ ],
1071
+ "related": ["bg", "fg", "disown", "ps"],
1072
+ "difficulty": "beginner",
1073
+ "extra_flags": {},
1074
+ },
1075
+
1076
+ "disown": {
1077
+ "man_url": "https://www.gnu.org/software/bash/manual/html_node/Job-Control-Builtins.html",
1078
+ "use_cases": [
1079
+ "Detach a running background job from the shell so it survives logout: disown %1",
1080
+ "Retroactively make a process immune to SIGHUP when you forgot to use nohup",
1081
+ "Remove all jobs from the shell's job table before logging out: disown -a",
1082
+ ],
1083
+ "gotchas": [
1084
+ "After disown, you can no longer use fg/bg/jobs to manage the process -- you must use kill with the PID directly",
1085
+ "disown only removes the job from the shell's table; it does not redirect output, so the process may still fail if it writes to the closed terminal",
1086
+ "disown -h keeps the job in the table but prevents SIGHUP, which is a safer option if you still want to track it",
1087
+ ],
1088
+ "related": ["nohup", "bg", "fg", "jobs", "screen", "tmux"],
1089
+ "difficulty": "intermediate",
1090
+ "extra_flags": {},
1091
+ },
1092
+
1093
+ "screen": {
1094
+ "man_url": "https://man7.org/linux/man-pages/man1/screen.1.html",
1095
+ "use_cases": [
1096
+ "Keep a long-running process alive after SSH disconnection: screen -S build, run command, then Ctrl-a d to detach",
1097
+ "Reattach to a running session after reconnecting: screen -r build",
1098
+ "Share a terminal session with another user for pair debugging: screen -x",
1099
+ ],
1100
+ "gotchas": [
1101
+ "screen uses Ctrl-a as its prefix key, which conflicts with the bash shortcut to go to the beginning of the line",
1102
+ "Dead sessions (marked as 'dead') must be wiped with screen -wipe before the name can be reused",
1103
+ "screen is being superseded by tmux, which has a more scriptable interface and better pane management",
1104
+ ],
1105
+ "related": ["tmux", "byobu", "nohup", "disown"],
1106
+ "difficulty": "intermediate",
1107
+ "extra_flags": {
1108
+ "-dm": "Start session in detached mode (useful in scripts)",
1109
+ "-X": "Send a command to a running session (e.g., screen -S name -X stuff 'command\\n')",
1110
+ },
1111
+ },
1112
+
1113
+ "tmux": {
1114
+ "man_url": "https://man7.org/linux/man-pages/man1/tmux.1.html",
1115
+ "use_cases": [
1116
+ "Keep long-running processes alive after SSH disconnection: tmux new -s work",
1117
+ "Split terminal into multiple panes for monitoring: Ctrl-b % (vertical) and Ctrl-b \" (horizontal)",
1118
+ "Share a terminal session with a colleague: tmux new -s pair, then they run tmux attach -t pair",
1119
+ "Script complex window layouts for development environments: tmux new-session -d, then send-keys commands",
1120
+ "Run multiple parallel tasks visible in one terminal: create panes for logs, servers, and a shell",
1121
+ ],
1122
+ "gotchas": [
1123
+ "tmux uses Ctrl-b as prefix by default (screen uses Ctrl-a) -- muscle memory conflicts are common when switching",
1124
+ "The tmux scrollback buffer requires entering copy mode (Ctrl-b [) to scroll; mouse wheel alone does not work without mouse mode enabled",
1125
+ "Nested tmux sessions (tmux inside tmux) require pressing the prefix twice to reach the inner session",
1126
+ "tmux uses a client-server model; killing the server (tmux kill-server) destroys all sessions",
1127
+ ],
1128
+ "related": ["screen", "byobu", "nohup", "disown"],
1129
+ "difficulty": "intermediate",
1130
+ "extra_flags": {
1131
+ "new-window": "Create a new window in the current session",
1132
+ "split-window": "Split the current pane horizontally or vertically",
1133
+ "send-keys": "Send keystrokes to a pane (useful for scripting)",
1134
+ "resize-pane": "Resize a pane by a specified number of cells",
1135
+ "source-file": "Load tmux configuration from a file",
1136
+ },
1137
+ },
1138
+
1139
+ "byobu": {
1140
+ "man_url": "https://www.byobu.org/documentation",
1141
+ "use_cases": [
1142
+ "Get a pre-configured tmux experience with status bar and keybindings out of the box",
1143
+ "Use function keys (F2 for new window, F3/F4 to switch) instead of memorizing tmux prefix commands",
1144
+ ],
1145
+ "gotchas": [
1146
+ "byobu wraps either tmux or screen depending on configuration; check which backend is active with byobu-select-backend",
1147
+ "Function key bindings may conflict with your terminal emulator's shortcuts",
1148
+ ],
1149
+ "related": ["tmux", "screen"],
1150
+ "difficulty": "beginner",
1151
+ "extra_flags": {},
1152
+ },
1153
+
1154
+ "systemctl": {
1155
+ "man_url": "https://man7.org/linux/man-pages/man1/systemctl.1.html",
1156
+ "use_cases": [
1157
+ "Start and enable a service in one command: systemctl enable --now nginx",
1158
+ "Check why a service failed: systemctl status nginx (shows recent logs inline)",
1159
+ "List all running services: systemctl list-units --type=service --state=running",
1160
+ "Reload service configuration without restarting: systemctl reload nginx",
1161
+ "Mask a service to prevent it from starting even manually: systemctl mask dangerous-service",
1162
+ ],
1163
+ "gotchas": [
1164
+ "enable does not start the service; it only configures it to start at boot. Use enable --now to do both",
1165
+ "daemon-reload is required after editing a .service unit file before restarting the service",
1166
+ "systemctl without arguments lists all loaded units, which can be overwhelming; use --type and --state filters",
1167
+ "A masked service cannot be started until unmasked; this is stronger than disable",
1168
+ ],
1169
+ "related": ["journalctl", "service", "init"],
1170
+ "difficulty": "intermediate",
1171
+ "extra_flags": {
1172
+ "reload": "Reload service configuration without full restart",
1173
+ "mask": "Completely prevent a service from being started",
1174
+ "unmask": "Remove the mask from a service",
1175
+ "is-active": "Check if a service is running (useful in scripts)",
1176
+ "is-enabled": "Check if a service is enabled at boot",
1177
+ "show": "Show properties of a unit for debugging",
1178
+ "--failed": "List only failed units",
1179
+ "edit": "Edit or create a unit file override",
1180
+ },
1181
+ },
1182
+
1183
+ "service": {
1184
+ "man_url": "https://man7.org/linux/man-pages/man8/service.8.html",
1185
+ "use_cases": [
1186
+ "Restart a service on any Linux system (works with both SysVinit and systemd): service nginx restart",
1187
+ "Check the status of all services at once: service --status-all",
1188
+ ],
1189
+ "gotchas": [
1190
+ "On systemd systems, service is a compatibility wrapper that redirects to systemctl -- use systemctl directly for full functionality",
1191
+ "service --status-all output uses +/- symbols that may not show the full picture on systemd systems",
1192
+ ],
1193
+ "related": ["systemctl", "init"],
1194
+ "difficulty": "beginner",
1195
+ "extra_flags": {},
1196
+ },
1197
+
1198
+ "journalctl": {
1199
+ "man_url": "https://man7.org/linux/man-pages/man1/journalctl.1.html",
1200
+ "use_cases": [
1201
+ "Follow logs for a specific service in real time: journalctl -u nginx -f",
1202
+ "View logs since the last boot: journalctl -b",
1203
+ "Find errors from the past hour: journalctl --since '1 hour ago' -p err",
1204
+ "Show the last 50 lines of a service log: journalctl -u postgresql -n 50",
1205
+ "Export logs in JSON for analysis: journalctl -u myapp -o json --since today",
1206
+ ],
1207
+ "gotchas": [
1208
+ "The journal can consume significant disk space; configure SystemMaxUse in journald.conf to limit it",
1209
+ "Without -u, journalctl shows logs from all units, which is noisy; always filter",
1210
+ "Timestamps use the system timezone by default; use --utc for UTC output",
1211
+ "Regular users may not see all logs; add yourself to the 'systemd-journal' group or use sudo",
1212
+ ],
1213
+ "related": ["systemctl", "dmesg", "syslog"],
1214
+ "difficulty": "intermediate",
1215
+ "extra_flags": {
1216
+ "-o": "Set output format (short, verbose, json, cat)",
1217
+ "--disk-usage": "Show how much disk space the journal uses",
1218
+ "--vacuum-size": "Reduce journal disk usage to specified size",
1219
+ "--vacuum-time": "Remove entries older than specified time",
1220
+ "-k": "Show only kernel messages (like dmesg)",
1221
+ "-r": "Show newest entries first (reverse chronological)",
1222
+ },
1223
+ },
1224
+
1225
+ "dmesg": {
1226
+ "man_url": "https://man7.org/linux/man-pages/man1/dmesg.1.html",
1227
+ "use_cases": [
1228
+ "Check for hardware issues after plugging in a USB device: dmesg -T | tail -20",
1229
+ "Diagnose boot problems by reviewing kernel messages: dmesg | less",
1230
+ "Watch for new kernel messages in real time: dmesg -T -w",
1231
+ "Filter for error-level messages only: dmesg -l err,crit,alert,emerg",
1232
+ ],
1233
+ "gotchas": [
1234
+ "dmesg timestamps are relative to boot by default; use -T for human-readable wall-clock times (note: -T can be inaccurate after suspend/resume)",
1235
+ "On newer systems, dmesg may require root or membership in specific groups to read kernel messages",
1236
+ "The kernel ring buffer has a fixed size; old messages are overwritten by new ones on busy systems",
1237
+ ],
1238
+ "related": ["journalctl", "syslog"],
1239
+ "difficulty": "intermediate",
1240
+ "extra_flags": {},
1241
+ },
1242
+
1243
+ "uptime": {
1244
+ "man_url": "https://man7.org/linux/man-pages/man1/uptime.1.html",
1245
+ "use_cases": [
1246
+ "Quick system health check: uptime shows load averages, user count, and time since last boot",
1247
+ "Check load averages to determine if a system is overloaded (compare to CPU count)",
1248
+ ],
1249
+ "gotchas": [
1250
+ "Load average numbers greater than your CPU count indicate the system is overloaded with waiting processes",
1251
+ "On Linux, load averages include processes waiting for I/O (D state), not just CPU -- so high load does not always mean high CPU usage",
1252
+ ],
1253
+ "related": ["w", "top", "free"],
1254
+ "difficulty": "beginner",
1255
+ "extra_flags": {},
1256
+ },
1257
+
1258
+ "free": {
1259
+ "man_url": "https://man7.org/linux/man-pages/man1/free.1.html",
1260
+ "use_cases": [
1261
+ "Check available memory: free -h (the 'available' column is what matters)",
1262
+ "Monitor memory usage over time: free -h -s 5 (refresh every 5 seconds)",
1263
+ "Quickly check swap usage to detect memory pressure",
1264
+ ],
1265
+ "gotchas": [
1266
+ "The 'used' column includes buffer/cache which Linux reclaims on demand -- look at 'available' for actual free memory",
1267
+ "High swap usage combined with constant swap activity (check with vmstat) indicates real memory pressure",
1268
+ "free shows a snapshot; for historical data use sar -r",
1269
+ ],
1270
+ "related": ["vmstat", "top", "sar"],
1271
+ "difficulty": "beginner",
1272
+ "extra_flags": {},
1273
+ },
1274
+
1275
+ "vmstat": {
1276
+ "man_url": "https://man7.org/linux/man-pages/man8/vmstat.8.html",
1277
+ "use_cases": [
1278
+ "Quick overview of system performance: vmstat 1 (updates every second)",
1279
+ "Check if system is CPU-bound (high us/sy), I/O-bound (high wa), or memory-bound (high si/so swap activity)",
1280
+ "Monitor context switches and interrupts: vmstat 1 and watch the cs and in columns",
1281
+ ],
1282
+ "gotchas": [
1283
+ "The first line of vmstat output shows averages since boot, not the current state; ignore it and look at subsequent lines",
1284
+ "The si/so columns show swap in/out; consistently non-zero values indicate memory pressure",
1285
+ "vmstat's compact format takes practice to read; w flag provides wider, easier-to-read output",
1286
+ ],
1287
+ "related": ["free", "iostat", "mpstat", "sar"],
1288
+ "difficulty": "intermediate",
1289
+ "extra_flags": {},
1290
+ },
1291
+
1292
+ "iostat": {
1293
+ "man_url": "https://man7.org/linux/man-pages/man1/iostat.1.html",
1294
+ "use_cases": [
1295
+ "Identify disk bottlenecks: iostat -x 1 (watch the %util and await columns)",
1296
+ "Monitor disk throughput in human-readable format: iostat -h 1",
1297
+ "Determine if slow performance is disk-related by checking average wait times",
1298
+ ],
1299
+ "gotchas": [
1300
+ "iostat is part of the sysstat package and may not be installed by default",
1301
+ "Like vmstat, the first report shows averages since boot; subsequent reports show current intervals",
1302
+ "%util at 100% does not always mean the disk is saturated (especially for SSDs and RAID arrays that handle concurrent I/O)",
1303
+ ],
1304
+ "related": ["vmstat", "sar", "iotop"],
1305
+ "difficulty": "intermediate",
1306
+ "extra_flags": {},
1307
+ },
1308
+
1309
+ "mpstat": {
1310
+ "man_url": "https://man7.org/linux/man-pages/man1/mpstat.1.html",
1311
+ "use_cases": [
1312
+ "Check per-CPU utilization to find single-threaded bottlenecks: mpstat -P ALL 1",
1313
+ "Identify if workload is evenly distributed across cores",
1314
+ "Monitor interrupt distribution: mpstat -I ALL 1",
1315
+ ],
1316
+ "gotchas": [
1317
+ "mpstat is part of the sysstat package and may not be installed by default",
1318
+ "If one CPU is at 100% while others are idle, the application likely has a single-threaded bottleneck",
1319
+ ],
1320
+ "related": ["vmstat", "iostat", "sar", "top"],
1321
+ "difficulty": "intermediate",
1322
+ "extra_flags": {},
1323
+ },
1324
+
1325
+ "sar": {
1326
+ "man_url": "https://man7.org/linux/man-pages/man1/sar.1.html",
1327
+ "use_cases": [
1328
+ "Review CPU usage from yesterday: sar -u -f /var/log/sa/sa$(date -d yesterday +%d)",
1329
+ "Check historical memory usage: sar -r",
1330
+ "Monitor network throughput: sar -n DEV 1 5",
1331
+ "Investigate a performance incident that happened at 3am: sar -u -s 03:00:00 -e 04:00:00",
1332
+ ],
1333
+ "gotchas": [
1334
+ "sar requires the sysstat package and its data collection service (sadc) must be enabled",
1335
+ "Data files are stored in /var/log/sa/ and rotate monthly; older data may be overwritten",
1336
+ "sar collects data at 10-minute intervals by default; for finer granularity, adjust the cron job",
1337
+ ],
1338
+ "related": ["vmstat", "iostat", "mpstat", "atop"],
1339
+ "difficulty": "advanced",
1340
+ "extra_flags": {},
1341
+ },
1342
+
1343
+ "lsof": {
1344
+ "man_url": "https://man7.org/linux/man-pages/man8/lsof.8.html",
1345
+ "use_cases": [
1346
+ "Find which process is using port 8080: lsof -i :8080",
1347
+ "List all network connections with process info: lsof -i -P -n",
1348
+ "Find all open files in a directory (why can't I unmount?): lsof +D /mnt/usb",
1349
+ "Get the PID of the process holding a file for scripting: lsof -t /path/to/file",
1350
+ "Find all files opened by a specific user: lsof -u www-data",
1351
+ ],
1352
+ "gotchas": [
1353
+ "lsof can be slow on systems with many open files; use specific filters (-i, -p, -u) rather than listing everything",
1354
+ "The -P flag prevents port number-to-name conversion, and -n prevents IP-to-hostname conversion; both speed up output significantly",
1355
+ "lsof requires root to see files opened by other users' processes",
1356
+ "Multiple selection flags are ORed by default; use -a to AND them together",
1357
+ ],
1358
+ "related": ["fuser", "ss", "netstat", "ps"],
1359
+ "difficulty": "intermediate",
1360
+ "extra_flags": {
1361
+ "-a": "AND selection criteria together (default is OR)",
1362
+ "-n": "Do not resolve IP addresses to hostnames",
1363
+ "-P": "Do not resolve port numbers to service names",
1364
+ "-r": "Repeat the listing every N seconds",
1365
+ "-F": "Produce output suitable for parsing by other programs",
1366
+ },
1367
+ },
1368
+
1369
+ "fuser": {
1370
+ "man_url": "https://man7.org/linux/man-pages/man1/fuser.1.html",
1371
+ "use_cases": [
1372
+ "Find which process is using a file: fuser -v /path/to/file",
1373
+ "Kill all processes accessing a stuck mount point: fuser -km /mnt/usb",
1374
+ "Find which process is listening on a TCP port: fuser -n tcp 8080",
1375
+ ],
1376
+ "gotchas": [
1377
+ "fuser -k kills ALL processes accessing the file/filesystem -- be very careful with this on system directories",
1378
+ "Use -i for interactive confirmation before killing",
1379
+ ],
1380
+ "related": ["lsof", "kill", "umount"],
1381
+ "difficulty": "intermediate",
1382
+ "extra_flags": {},
1383
+ },
1384
+
1385
+ "strace": {
1386
+ "man_url": "https://man7.org/linux/man-pages/man1/strace.1.html",
1387
+ "use_cases": [
1388
+ "Debug why a program cannot find a config file: strace -e trace=open,openat ./program 2>&1 | grep config",
1389
+ "Trace a running process: strace -p PID",
1390
+ "Profile system call timing: strace -c ./program",
1391
+ "Debug network connectivity: strace -e trace=network ./program",
1392
+ "Find why a program hangs: strace -p PID and see which syscall it blocks on",
1393
+ ],
1394
+ "gotchas": [
1395
+ "strace adds significant overhead (10-100x slowdown); do not use in production unless absolutely necessary",
1396
+ "strace output goes to stderr by default; use -o to write to a file for analysis",
1397
+ "The -s flag controls max string length printed (default 32); increase it to see full filenames and data: -s 256",
1398
+ "Attaching to a running process with -p requires root or matching user and ptrace permissions",
1399
+ ],
1400
+ "related": ["ltrace", "perf", "gdb"],
1401
+ "difficulty": "advanced",
1402
+ "extra_flags": {
1403
+ "-T": "Show time spent in each system call",
1404
+ "-r": "Print relative timestamp for each call",
1405
+ "-y": "Print paths associated with file descriptor arguments",
1406
+ "-e trace=file": "Trace only file-related system calls",
1407
+ "-e trace=network": "Trace only network-related system calls",
1408
+ "-e trace=process": "Trace only process-related system calls",
1409
+ },
1410
+ },
1411
+
1412
+ "ltrace": {
1413
+ "man_url": "https://man7.org/linux/man-pages/man1/ltrace.1.html",
1414
+ "use_cases": [
1415
+ "Trace library calls to understand how a program uses libc: ltrace ./program",
1416
+ "Profile library call frequency and timing: ltrace -c ./program",
1417
+ "Debug dynamic linking issues by watching library function calls",
1418
+ ],
1419
+ "gotchas": [
1420
+ "ltrace does not work with statically linked binaries since there are no dynamic library calls to intercept",
1421
+ "ltrace may not work correctly on some architectures or with PIE (position-independent executables)",
1422
+ "ltrace has significant overhead; use -e to filter specific functions for performance-sensitive tracing",
1423
+ ],
1424
+ "related": ["strace", "perf", "gdb", "ldd"],
1425
+ "difficulty": "advanced",
1426
+ "extra_flags": {},
1427
+ },
1428
+
1429
+ "perf": {
1430
+ "man_url": "https://man7.org/linux/man-pages/man1/perf.1.html",
1431
+ "use_cases": [
1432
+ "Count hardware performance events: perf stat ./myprogram",
1433
+ "Profile CPU hotspots with stack traces: perf record -g ./myprogram, then perf report",
1434
+ "Real-time system-wide profiling like top: perf top",
1435
+ "Find cache misses and branch mispredictions: perf stat -e cache-misses,branch-misses ./program",
1436
+ ],
1437
+ "gotchas": [
1438
+ "perf requires root or specific kernel settings (perf_event_paranoid) for most operations",
1439
+ "perf record generates perf.data files that can be large; use --call-graph dwarf for accurate stack traces",
1440
+ "Kernel symbols require /proc/kallsyms to be readable and debug symbols installed",
1441
+ ],
1442
+ "related": ["strace", "time", "gprof"],
1443
+ "difficulty": "advanced",
1444
+ "extra_flags": {
1445
+ "annotate": "Show per-line CPU usage of a function in source or assembly",
1446
+ "bench": "Run built-in benchmarks for memory, scheduling, etc.",
1447
+ "-e": "Select specific events to count or sample",
1448
+ },
1449
+ },
1450
+
1451
+ "time": {
1452
+ "man_url": "https://man7.org/linux/man-pages/man1/time.1.html",
1453
+ "use_cases": [
1454
+ "Measure how long a build takes: time make -j8",
1455
+ "Compare performance of different implementations: time ./version1 vs time ./version2",
1456
+ "Identify if a slow command is CPU-bound (high user time) or I/O-bound (real >> user+sys)",
1457
+ ],
1458
+ "gotchas": [
1459
+ "Bash has a built-in 'time' keyword that behaves differently from /usr/bin/time; use \\time or command time to get the external version with more options",
1460
+ "The bash builtin 'time' cannot output to a file directly; use { time command; } 2> timing.txt",
1461
+ "'real' is wall-clock time, 'user' is CPU time in user space, 'sys' is CPU time in kernel space; real > user+sys indicates I/O waits",
1462
+ ],
1463
+ "related": ["perf", "strace", "timeout"],
1464
+ "difficulty": "beginner",
1465
+ "extra_flags": {
1466
+ "-v": "Verbose output with detailed resource usage (GNU time only)",
1467
+ "-o": "Write output to file (GNU time only)",
1468
+ "-f": "Custom output format string (GNU time only)",
1469
+ },
1470
+ },
1471
+
1472
+ "timeout": {
1473
+ "man_url": "https://man7.org/linux/man-pages/man1/timeout.1.html",
1474
+ "use_cases": [
1475
+ "Prevent a curl request from hanging indefinitely: timeout 30 curl https://slow-api.example.com",
1476
+ "Set a hard limit on test execution in CI: timeout -k 10 300 pytest tests/",
1477
+ "Kill a process that should complete within a time window: timeout 60 ./batch-job.sh",
1478
+ ],
1479
+ "gotchas": [
1480
+ "timeout sends SIGTERM by default; the process can ignore it. Use -k to send SIGKILL after an additional grace period",
1481
+ "Exit code 124 means the command timed out; other exit codes come from the command itself",
1482
+ "The duration format supports s (seconds), m (minutes), h (hours), d (days); default is seconds",
1483
+ ],
1484
+ "related": ["kill", "time", "watch"],
1485
+ "difficulty": "beginner",
1486
+ "extra_flags": {},
1487
+ },
1488
+
1489
+ "watch": {
1490
+ "man_url": "https://man7.org/linux/man-pages/man1/watch.1.html",
1491
+ "use_cases": [
1492
+ "Monitor disk space usage in real time: watch -n 5 df -h",
1493
+ "Watch a deployment roll out: watch -n 2 kubectl get pods",
1494
+ "Track file changes: watch -d ls -la /path/to/dir",
1495
+ "Monitor network connections: watch -n 1 'ss -tn | wc -l'",
1496
+ ],
1497
+ "gotchas": [
1498
+ "The command must be quoted if it contains pipes or special characters: watch 'cmd1 | cmd2'",
1499
+ "watch runs the command through sh -c, so bash-specific syntax may not work; use explicit bash -c if needed",
1500
+ "The -d flag highlights changes between refreshes, making differences easy to spot",
1501
+ ],
1502
+ "related": ["tail", "timeout"],
1503
+ "difficulty": "beginner",
1504
+ "extra_flags": {
1505
+ "-t": "Turn off the header showing interval and command",
1506
+ "-g": "Exit when the output of the command changes",
1507
+ "-e": "Freeze output and exit on command error",
1508
+ "-c": "Interpret ANSI color sequences",
1509
+ "-x": "Pass command to exec instead of sh -c (avoids shell interpretation)",
1510
+ },
1511
+ },
1512
+
1513
+ "wait": {
1514
+ "man_url": "https://www.gnu.org/software/bash/manual/html_node/Job-Control-Builtins.html",
1515
+ "use_cases": [
1516
+ "Wait for all background jobs to finish: command1 & command2 & wait",
1517
+ "Get the exit status of a specific background process: wait $PID; echo $?",
1518
+ "Wait for any one of several background jobs to complete: wait -n",
1519
+ "Synchronize parallel tasks in a shell script before proceeding to the next stage",
1520
+ ],
1521
+ "gotchas": [
1522
+ "wait without arguments waits for ALL background children, not just the most recent one",
1523
+ "wait only works for child processes of the current shell; it cannot wait for arbitrary PIDs from other sessions",
1524
+ "The -n flag (wait for any single job) is a bash 4.3+ feature; it is not available in older bash or POSIX sh",
1525
+ ],
1526
+ "related": ["bg", "fg", "jobs", "kill"],
1527
+ "difficulty": "intermediate",
1528
+ "extra_flags": {},
1529
+ },
1530
+
1531
+ "sleep": {
1532
+ "man_url": "https://man7.org/linux/man-pages/man1/sleep.1.html",
1533
+ "use_cases": [
1534
+ "Add a delay between retries in a loop: while ! curl -s host; do sleep 5; done",
1535
+ "Rate-limit requests in a script: for url in $urls; do curl $url; sleep 1; done",
1536
+ "Wait for a service to start: sleep 10 && curl http://localhost:8080/health",
1537
+ ],
1538
+ "gotchas": [
1539
+ "sleep accepts decimal values (sleep 0.5) on GNU/Linux but not on all Unix systems; check portability requirements",
1540
+ "sleep supports suffixes: s (seconds, default), m (minutes), h (hours), d (days)",
1541
+ "Using sleep in a tight loop wastes time; consider using inotifywait, systemd timers, or polling with exponential backoff instead",
1542
+ ],
1543
+ "related": ["watch", "timeout", "wait"],
1544
+ "difficulty": "beginner",
1545
+ "extra_flags": {},
1546
+ },
1547
+
1548
+ "cron": {
1549
+ "man_url": "https://man7.org/linux/man-pages/man8/cron.8.html",
1550
+ "use_cases": [
1551
+ "cron is the daemon that runs scheduled jobs defined in crontab files",
1552
+ "Ensure cron is running on your system: systemctl status cron",
1553
+ ],
1554
+ "gotchas": [
1555
+ "cron runs commands with a minimal environment; PATH, HOME, and other variables may not be what you expect -- always use full paths in cron jobs",
1556
+ "cron has no built-in logging of job output; redirect stdout/stderr in the crontab entry or mail will be sent to the user",
1557
+ "cron does not run missed jobs if the system was off during the scheduled time; use anacron for machines that are not always on",
1558
+ ],
1559
+ "related": ["crontab", "at", "systemctl"],
1560
+ "difficulty": "intermediate",
1561
+ "extra_flags": {},
1562
+ },
1563
+
1564
+ "crontab": {
1565
+ "man_url": "https://man7.org/linux/man-pages/man1/crontab.1.html",
1566
+ "use_cases": [
1567
+ "Edit your crontab: crontab -e",
1568
+ "Run a backup every night at 2am: add '0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1'",
1569
+ "List current cron jobs: crontab -l",
1570
+ "Remove all cron jobs: crontab -r (use with caution)",
1571
+ ],
1572
+ "gotchas": [
1573
+ "crontab -r removes ALL your cron jobs without confirmation; there is no undo",
1574
+ "Cron job environment is minimal -- PATH is typically just /usr/bin:/bin. Always use absolute paths for commands",
1575
+ "The cron expression minute field is 0-59; forgetting this and using * means the job runs every minute, not once",
1576
+ "Percent signs (%) in crontab lines are treated as newlines; escape them with backslash or put the command in a script",
1577
+ ],
1578
+ "related": ["cron", "at", "batch"],
1579
+ "difficulty": "intermediate",
1580
+ "extra_flags": {},
1581
+ },
1582
+
1583
+ "at": {
1584
+ "man_url": "https://man7.org/linux/man-pages/man1/at.1.html",
1585
+ "use_cases": [
1586
+ "Schedule a one-time job: echo 'backup.sh' | at 2am",
1587
+ "Run a command in one hour: at now + 1 hour -f script.sh",
1588
+ "List pending jobs: atq (or at -l)",
1589
+ ],
1590
+ "gotchas": [
1591
+ "at requires the atd daemon to be running",
1592
+ "at jobs run with the environment captured at scheduling time, not the environment at execution time",
1593
+ "at is for one-time scheduling; use crontab for recurring tasks",
1594
+ ],
1595
+ "related": ["crontab", "batch", "sleep"],
1596
+ "difficulty": "intermediate",
1597
+ "extra_flags": {},
1598
+ },
1599
+
1600
+ "batch": {
1601
+ "man_url": "https://man7.org/linux/man-pages/man1/batch.1.html",
1602
+ "use_cases": [
1603
+ "Queue a heavy compilation for when the system is idle: echo 'make -j8' | batch",
1604
+ "Schedule resource-intensive work to run during low load automatically",
1605
+ ],
1606
+ "gotchas": [
1607
+ "batch executes when load average drops below 1.5 (default); this threshold may never be reached on busy systems",
1608
+ "Like at, requires the atd daemon",
1609
+ ],
1610
+ "related": ["at", "crontab", "nice"],
1611
+ "difficulty": "intermediate",
1612
+ "extra_flags": {},
1613
+ },
1614
+
1615
+ "shutdown": {
1616
+ "man_url": "https://man7.org/linux/man-pages/man8/shutdown.8.html",
1617
+ "use_cases": [
1618
+ "Shut down immediately: shutdown -h now",
1619
+ "Schedule a reboot with user warning: shutdown -r +10 'Rebooting for kernel update'",
1620
+ "Cancel a pending shutdown: shutdown -c",
1621
+ ],
1622
+ "gotchas": [
1623
+ "shutdown sends wall messages to logged-in users; use --no-wall to suppress in automated scenarios",
1624
+ "On systemd systems, 'shutdown +5' creates a transient timer; systemctl status shutdown.target shows the scheduled time",
1625
+ ],
1626
+ "related": ["reboot", "poweroff", "halt", "systemctl"],
1627
+ "difficulty": "beginner",
1628
+ "extra_flags": {},
1629
+ },
1630
+
1631
+ "reboot": {
1632
+ "man_url": "https://man7.org/linux/man-pages/man8/reboot.8.html",
1633
+ "use_cases": [
1634
+ "Restart the system immediately: sudo reboot",
1635
+ "Force reboot a hung system: sudo reboot -f (last resort, may cause data loss)",
1636
+ ],
1637
+ "gotchas": [
1638
+ "reboot -f bypasses normal shutdown procedures and can cause data loss; prefer 'shutdown -r now'",
1639
+ "On remote servers, ensure you can access the console before forcing a reboot in case it does not come back",
1640
+ ],
1641
+ "related": ["shutdown", "poweroff", "halt", "systemctl"],
1642
+ "difficulty": "beginner",
1643
+ "extra_flags": {},
1644
+ },
1645
+
1646
+ "halt": {
1647
+ "man_url": "https://man7.org/linux/man-pages/man8/halt.8.html",
1648
+ "use_cases": [
1649
+ "Stop the system without powering off the hardware: sudo halt",
1650
+ "On modern systems, halt usually behaves identically to poweroff",
1651
+ ],
1652
+ "gotchas": [
1653
+ "On modern systemd systems, halt, poweroff, and reboot all redirect to systemctl",
1654
+ "halt -f forcibly halts without proper shutdown, risking filesystem corruption",
1655
+ ],
1656
+ "related": ["shutdown", "poweroff", "reboot"],
1657
+ "difficulty": "beginner",
1658
+ "extra_flags": {},
1659
+ },
1660
+
1661
+ "poweroff": {
1662
+ "man_url": "https://man7.org/linux/man-pages/man8/shutdown.8.html",
1663
+ "use_cases": [
1664
+ "Cleanly power off a server: sudo poweroff",
1665
+ "Equivalent to shutdown -h now on modern systems",
1666
+ ],
1667
+ "gotchas": [
1668
+ "poweroff -f bypasses init and can cause filesystem corruption",
1669
+ ],
1670
+ "related": ["shutdown", "halt", "reboot"],
1671
+ "difficulty": "beginner",
1672
+ "extra_flags": {},
1673
+ },
1674
+
1675
+ "init": {
1676
+ "man_url": "https://man7.org/linux/man-pages/man1/init.1.html",
1677
+ "use_cases": [
1678
+ "Switch to single-user mode for emergency maintenance: sudo init 1",
1679
+ "On SysVinit systems, change runlevels to control which services run",
1680
+ ],
1681
+ "gotchas": [
1682
+ "On systemd systems, init is symlinked to systemd; use systemctl isolate instead of init for changing targets",
1683
+ "init 0 halts and init 6 reboots; confusing these can be catastrophic on remote servers",
1684
+ ],
1685
+ "related": ["systemctl", "runlevel", "shutdown"],
1686
+ "difficulty": "advanced",
1687
+ "extra_flags": {},
1688
+ },
1689
+
1690
+ "runlevel": {
1691
+ "man_url": "https://man7.org/linux/man-pages/man8/runlevel.8.html",
1692
+ "use_cases": [
1693
+ "Check the current runlevel on a SysVinit system: runlevel",
1694
+ ],
1695
+ "gotchas": [
1696
+ "runlevel is a SysVinit concept; on systemd systems, use systemctl get-default for the equivalent information",
1697
+ "Output shows two values: previous and current runlevel; N means no previous runlevel was recorded",
1698
+ ],
1699
+ "related": ["init", "systemctl"],
1700
+ "difficulty": "intermediate",
1701
+ "extra_flags": {},
1702
+ },
1703
+
1704
+ "uname": {
1705
+ "man_url": "https://man7.org/linux/man-pages/man1/uname.1.html",
1706
+ "use_cases": [
1707
+ "Print all system information: uname -a",
1708
+ "Detect CPU architecture for cross-platform scripts: uname -m",
1709
+ "Check kernel version: uname -r",
1710
+ ],
1711
+ "gotchas": [
1712
+ "uname shows the kernel information, not the distribution name; use /etc/os-release or lsb_release for distro info",
1713
+ "Inside Docker containers, uname shows the host kernel version, not the container's base image version",
1714
+ ],
1715
+ "related": ["hostname", "hostnamectl", "lsb_release"],
1716
+ "difficulty": "beginner",
1717
+ "extra_flags": {},
1718
+ },
1719
+
1720
+ "hostname": {
1721
+ "man_url": "https://man7.org/linux/man-pages/man1/hostname.1.html",
1722
+ "use_cases": [
1723
+ "Display the system hostname: hostname",
1724
+ "Get all IP addresses of the machine: hostname -I",
1725
+ "Get the FQDN: hostname -f",
1726
+ ],
1727
+ "gotchas": [
1728
+ "Setting hostname with the hostname command is temporary; use hostnamectl for persistent changes on systemd systems",
1729
+ "hostname -I may show multiple IPs if the machine has multiple interfaces or addresses",
1730
+ ],
1731
+ "related": ["hostnamectl", "uname"],
1732
+ "difficulty": "beginner",
1733
+ "extra_flags": {},
1734
+ },
1735
+
1736
+ "hostnamectl": {
1737
+ "man_url": "https://man7.org/linux/man-pages/man1/hostnamectl.1.html",
1738
+ "use_cases": [
1739
+ "Permanently set the system hostname: sudo hostnamectl set-hostname webserver01",
1740
+ "Display all hostname types and machine info: hostnamectl status",
1741
+ ],
1742
+ "gotchas": [
1743
+ "hostnamectl requires systemd; it does not work on SysVinit systems",
1744
+ "Changing the hostname does not update /etc/hosts automatically; update it manually to avoid sudo and other resolution issues",
1745
+ ],
1746
+ "related": ["hostname", "uname"],
1747
+ "difficulty": "beginner",
1748
+ "extra_flags": {},
1749
+ },
1750
+
1751
+ "timedatectl": {
1752
+ "man_url": "https://man7.org/linux/man-pages/man1/timedatectl.1.html",
1753
+ "use_cases": [
1754
+ "Check current time, timezone, and NTP sync status: timedatectl",
1755
+ "Set the timezone: sudo timedatectl set-timezone America/New_York",
1756
+ "Enable NTP synchronization: sudo timedatectl set-ntp true",
1757
+ ],
1758
+ "gotchas": [
1759
+ "timedatectl requires systemd and conflicts with running ntpd or chrony in some configurations",
1760
+ "Setting time manually with set-time disables NTP; re-enable with set-ntp true afterward",
1761
+ ],
1762
+ "related": ["date", "hostnamectl", "localectl"],
1763
+ "difficulty": "beginner",
1764
+ "extra_flags": {},
1765
+ },
1766
+
1767
+ "localectl": {
1768
+ "man_url": "https://man7.org/linux/man-pages/man1/localectl.1.html",
1769
+ "use_cases": [
1770
+ "View current locale settings: localectl",
1771
+ "Set the system locale: sudo localectl set-locale LANG=en_US.UTF-8",
1772
+ "Change the keyboard layout: sudo localectl set-keymap us",
1773
+ ],
1774
+ "gotchas": [
1775
+ "localectl changes are system-wide and require root; they take effect on next login, not the current session",
1776
+ "The locale must be generated first (with locale-gen or similar) before it can be set with localectl",
1777
+ ],
1778
+ "related": ["timedatectl", "hostnamectl"],
1779
+ "difficulty": "beginner",
1780
+ "extra_flags": {},
1781
+ },
1782
+
1783
+ # =========================================================================
1784
+ # PERMISSIONS COMMANDS
1785
+ # =========================================================================
1786
+
1787
+ "sudo": {
1788
+ "man_url": "https://man7.org/linux/man-pages/man8/sudo.8.html",
1789
+ "use_cases": [
1790
+ "Run a command as root: sudo apt update",
1791
+ "Edit a system file with your preferred editor: sudo -e /etc/hosts (uses SUDO_EDITOR or EDITOR)",
1792
+ "Run a command as a different user: sudo -u postgres psql",
1793
+ "Check what you are allowed to run: sudo -l",
1794
+ "Open a root shell: sudo -i (login shell) or sudo -s (non-login shell)",
1795
+ ],
1796
+ "gotchas": [
1797
+ "sudo caches credentials for a short time (typically 15 minutes); use sudo -k to clear the cache if security is a concern",
1798
+ "Environment variables are reset by default; use sudo -E to preserve them, or configure env_keep in sudoers",
1799
+ "Never edit /etc/sudoers directly; always use visudo which validates syntax and prevents lockouts",
1800
+ "sudo !! repeats the last command with sudo -- a common shortcut when you forget to use sudo",
1801
+ "Piping with sudo requires careful placement: echo 'text' | sudo tee /etc/file (not sudo echo 'text' > /etc/file which fails)",
1802
+ ],
1803
+ "related": ["su", "doas", "visudo"],
1804
+ "difficulty": "beginner",
1805
+ "extra_flags": {
1806
+ "-e": "Edit a file with the sudoers-configured editor (sudoedit)",
1807
+ "-H": "Set HOME to the target user's home directory",
1808
+ "-A": "Use a helper program for password input (SUDO_ASKPASS)",
1809
+ "--preserve-env": "More explicit form of -E to preserve environment",
1810
+ },
1811
+ },
1812
+
1813
+ "su": {
1814
+ "man_url": "https://man7.org/linux/man-pages/man1/su.1.html",
1815
+ "use_cases": [
1816
+ "Switch to root with a full login environment: su - (or su -l root)",
1817
+ "Run a single command as another user: su -c 'pg_dump mydb' postgres",
1818
+ "Switch to a service account for debugging: su - www-data -s /bin/bash",
1819
+ ],
1820
+ "gotchas": [
1821
+ "su requires the target user's password (not your own like sudo); root password is needed for su -",
1822
+ "Without the dash (-), su does not start a login shell and inherits the current environment, which can cause unexpected behavior",
1823
+ "Many modern distributions disable the root password by default, making su - fail; use sudo -i instead",
1824
+ ],
1825
+ "related": ["sudo", "doas", "newgrp"],
1826
+ "difficulty": "beginner",
1827
+ "extra_flags": {
1828
+ "-g": "Set primary group (root only)",
1829
+ "-G": "Set supplementary groups (root only)",
1830
+ "-P": "Create a pseudo-terminal for the session",
1831
+ },
1832
+ },
1833
+
1834
+ "doas": {
1835
+ "man_url": "https://man.openbsd.org/doas",
1836
+ "use_cases": [
1837
+ "Run a privileged command with simpler configuration than sudo: doas apt update",
1838
+ "Use on OpenBSD systems or Linux systems configured with doas as a sudo alternative",
1839
+ ],
1840
+ "gotchas": [
1841
+ "doas configuration (/etc/doas.conf) uses a completely different syntax from sudoers",
1842
+ "doas has fewer features than sudo (no command logging, no group-based sudo, no env editing); it trades features for simplicity and security",
1843
+ "doas is not installed by default on most Linux distributions",
1844
+ ],
1845
+ "related": ["sudo", "su"],
1846
+ "difficulty": "intermediate",
1847
+ "extra_flags": {},
1848
+ },
1849
+
1850
+ "chroot": {
1851
+ "man_url": "https://man7.org/linux/man-pages/man1/chroot.1.html",
1852
+ "use_cases": [
1853
+ "Repair a broken system from a live USB: mount /dev/sda1 /mnt && chroot /mnt /bin/bash",
1854
+ "Build packages in a clean environment isolated from the host system",
1855
+ "Create a minimal sandbox for running untrusted programs (though containers are preferred now)",
1856
+ ],
1857
+ "gotchas": [
1858
+ "chroot is not a security boundary -- a root process inside a chroot can escape it. Use containers or namespaces for real isolation",
1859
+ "The chroot directory must contain all necessary binaries, libraries, and device files; a bare directory will fail immediately",
1860
+ "You typically need to mount /proc, /sys, and /dev inside the chroot for many commands to work properly",
1861
+ ],
1862
+ "related": ["docker", "unshare", "mount"],
1863
+ "difficulty": "advanced",
1864
+ "extra_flags": {},
1865
+ },
1866
+
1867
+ "newgrp": {
1868
+ "man_url": "https://man7.org/linux/man-pages/man1/newgrp.1.html",
1869
+ "use_cases": [
1870
+ "Switch your primary group to create files owned by a different group: newgrp developers",
1871
+ "Access a group-restricted resource after being added to a group without logging out: newgrp docker",
1872
+ ],
1873
+ "gotchas": [
1874
+ "newgrp starts a new shell; when you exit, you return to the original shell with the original group",
1875
+ "If you were just added to a group, newgrp avoids the need to log out and back in to pick up the new group membership",
1876
+ ],
1877
+ "related": ["groups", "id", "usermod"],
1878
+ "difficulty": "intermediate",
1879
+ "extra_flags": {},
1880
+ },
1881
+
1882
+ "id": {
1883
+ "man_url": "https://man7.org/linux/man-pages/man1/id.1.html",
1884
+ "use_cases": [
1885
+ "Check your current UID, GID, and all group memberships: id",
1886
+ "Verify a user's groups for permission debugging: id username",
1887
+ "Get just the username in a script: id -un",
1888
+ ],
1889
+ "gotchas": [
1890
+ "id shows effective UID/GID which may differ from real UID/GID if using setuid programs",
1891
+ "Group membership changes from usermod require a new login to take effect; id will show the old groups until then",
1892
+ ],
1893
+ "related": ["whoami", "groups", "who"],
1894
+ "difficulty": "beginner",
1895
+ "extra_flags": {},
1896
+ },
1897
+
1898
+ "whoami": {
1899
+ "man_url": "https://man7.org/linux/man-pages/man1/whoami.1.html",
1900
+ "use_cases": [
1901
+ "Quick check in a script whether running as root: [ $(whoami) = root ] || exit 1",
1902
+ "Embed the username in log messages or file paths",
1903
+ ],
1904
+ "gotchas": [
1905
+ "whoami prints the effective username, which may be different from the login name if you used su or sudo -u",
1906
+ ],
1907
+ "related": ["id", "who", "logname"],
1908
+ "difficulty": "beginner",
1909
+ "extra_flags": {},
1910
+ },
1911
+
1912
+ "groups": {
1913
+ "man_url": "https://man7.org/linux/man-pages/man1/groups.1.html",
1914
+ "use_cases": [
1915
+ "Check which groups you belong to: groups",
1916
+ "Verify a user has the expected group memberships: groups username",
1917
+ ],
1918
+ "gotchas": [
1919
+ "groups shows the groups from the current login session; recently added groups via usermod -aG require a new login to appear",
1920
+ "groups is equivalent to id -Gn but with a different output format",
1921
+ ],
1922
+ "related": ["id", "usermod", "newgrp"],
1923
+ "difficulty": "beginner",
1924
+ "extra_flags": {},
1925
+ },
1926
+
1927
+ "users": {
1928
+ "man_url": "https://man7.org/linux/man-pages/man1/users.1.html",
1929
+ "use_cases": [
1930
+ "Quick list of who is logged in: users",
1931
+ "Count logged-in users: users | wc -w",
1932
+ ],
1933
+ "gotchas": [
1934
+ "users shows each login session, so a user logged in multiple times appears multiple times",
1935
+ ],
1936
+ "related": ["who", "w", "last"],
1937
+ "difficulty": "beginner",
1938
+ "extra_flags": {},
1939
+ },
1940
+
1941
+ "who": {
1942
+ "man_url": "https://man7.org/linux/man-pages/man1/who.1.html",
1943
+ "use_cases": [
1944
+ "See who is logged in and from where: who",
1945
+ "Check the last boot time: who -b",
1946
+ "Show idle time to find inactive sessions: who -u",
1947
+ ],
1948
+ "gotchas": [
1949
+ "who reads /var/run/utmp which may not include all active sessions (e.g., some GUI sessions may not register)",
1950
+ "'who am i' shows the original login name even after su, unlike whoami which shows the effective user",
1951
+ ],
1952
+ "related": ["w", "users", "last", "whoami"],
1953
+ "difficulty": "beginner",
1954
+ "extra_flags": {},
1955
+ },
1956
+
1957
+ "w": {
1958
+ "man_url": "https://man7.org/linux/man-pages/man1/w.1.html",
1959
+ "use_cases": [
1960
+ "Quick overview of system load and user activity: w",
1961
+ "Check what commands active users are running (shown in the WHAT column)",
1962
+ "Identify idle user sessions that may need to be terminated",
1963
+ ],
1964
+ "gotchas": [
1965
+ "w shows a combination of who, uptime, and per-user process info -- it is the most information-dense of the who-family commands",
1966
+ ],
1967
+ "related": ["who", "users", "uptime", "last"],
1968
+ "difficulty": "beginner",
1969
+ "extra_flags": {},
1970
+ },
1971
+
1972
+ "last": {
1973
+ "man_url": "https://man7.org/linux/man-pages/man1/last.1.html",
1974
+ "use_cases": [
1975
+ "View recent login history: last -n 20",
1976
+ "Check system reboot history: last reboot",
1977
+ "Investigate logins by a specific user: last username",
1978
+ ],
1979
+ "gotchas": [
1980
+ "last reads /var/log/wtmp which may be rotated; historical data beyond the rotation period is lost",
1981
+ "On systems with many logins, unfiltered 'last' produces very long output; always use -n or a username filter",
1982
+ ],
1983
+ "related": ["lastlog", "who", "w"],
1984
+ "difficulty": "beginner",
1985
+ "extra_flags": {},
1986
+ },
1987
+
1988
+ "lastlog": {
1989
+ "man_url": "https://man7.org/linux/man-pages/man8/lastlog.8.html",
1990
+ "use_cases": [
1991
+ "Audit which accounts have been used recently: lastlog",
1992
+ "Find stale accounts that have never logged in: lastlog -b 365",
1993
+ "Check when a specific user last logged in: lastlog -u username",
1994
+ ],
1995
+ "gotchas": [
1996
+ "Service accounts with /sbin/nologin shell show 'Never logged in' which is expected",
1997
+ "On systems with many users, the output can be very long; use -u or -t to filter",
1998
+ ],
1999
+ "related": ["last", "who"],
2000
+ "difficulty": "beginner",
2001
+ "extra_flags": {},
2002
+ },
2003
+
2004
+ "finger": {
2005
+ "man_url": "https://man7.org/linux/man-pages/man1/finger.1.html",
2006
+ "use_cases": [
2007
+ "Display user account details: finger username",
2008
+ "Check a user's real name, login time, and shell",
2009
+ ],
2010
+ "gotchas": [
2011
+ "finger is considered a security risk because it can expose user information remotely; it is often uninstalled or disabled on modern systems",
2012
+ "The finger daemon (fingerd) is almost never enabled on production systems",
2013
+ ],
2014
+ "related": ["id", "who", "w"],
2015
+ "difficulty": "beginner",
2016
+ "extra_flags": {},
2017
+ },
2018
+
2019
+ "useradd": {
2020
+ "man_url": "https://man7.org/linux/man-pages/man8/useradd.8.html",
2021
+ "use_cases": [
2022
+ "Create a regular user with home directory: useradd -m -s /bin/bash newuser",
2023
+ "Create a system service account: useradd -r -s /sbin/nologin myservice",
2024
+ "Create a user with specific group memberships: useradd -m -G sudo,docker newuser",
2025
+ ],
2026
+ "gotchas": [
2027
+ "useradd without -m does not create a home directory on many distributions -- always use -m for regular users",
2028
+ "useradd does not set a password; run passwd username afterward, or the account is locked",
2029
+ "On Debian/Ubuntu, adduser is a higher-level wrapper that is more user-friendly than raw useradd",
2030
+ ],
2031
+ "related": ["userdel", "usermod", "passwd", "groupadd"],
2032
+ "difficulty": "intermediate",
2033
+ "extra_flags": {},
2034
+ },
2035
+
2036
+ "userdel": {
2037
+ "man_url": "https://man7.org/linux/man-pages/man8/userdel.8.html",
2038
+ "use_cases": [
2039
+ "Remove a user and their home directory: userdel -r username",
2040
+ "Remove just the account, keeping files for archival: userdel username",
2041
+ ],
2042
+ "gotchas": [
2043
+ "userdel -r permanently deletes the home directory and mail spool; there is no undo",
2044
+ "userdel cannot remove a user who is currently logged in unless -f is used",
2045
+ "Files owned by the deleted user outside their home directory become orphaned (owned by a numeric UID); find and reassign them",
2046
+ ],
2047
+ "related": ["useradd", "usermod"],
2048
+ "difficulty": "intermediate",
2049
+ "extra_flags": {},
2050
+ },
2051
+
2052
+ "usermod": {
2053
+ "man_url": "https://man7.org/linux/man-pages/man8/usermod.8.html",
2054
+ "use_cases": [
2055
+ "Add a user to the docker group: usermod -aG docker username",
2056
+ "Change a user's login shell: usermod -s /bin/zsh username",
2057
+ "Lock a compromised account immediately: usermod -L username",
2058
+ ],
2059
+ "gotchas": [
2060
+ "Using -G without -a REPLACES all supplementary groups, potentially removing the user from sudo and other critical groups; always use -aG",
2061
+ "Group changes require the user to log out and back in to take effect",
2062
+ "usermod -L locks the password but does not prevent SSH key-based login; for full lockout, also change the shell to /sbin/nologin",
2063
+ ],
2064
+ "related": ["useradd", "userdel", "passwd", "groups"],
2065
+ "difficulty": "intermediate",
2066
+ "extra_flags": {},
2067
+ },
2068
+
2069
+ "groupadd": {
2070
+ "man_url": "https://man7.org/linux/man-pages/man8/groupadd.8.html",
2071
+ "use_cases": [
2072
+ "Create a group for shared project access: groupadd developers",
2073
+ "Create a system group for a daemon: groupadd -r myservice",
2074
+ ],
2075
+ "gotchas": [
2076
+ "Groups are not useful until users are added to them with usermod -aG",
2077
+ ],
2078
+ "related": ["groupdel", "groupmod", "usermod"],
2079
+ "difficulty": "intermediate",
2080
+ "extra_flags": {},
2081
+ },
2082
+
2083
+ "groupdel": {
2084
+ "man_url": "https://man7.org/linux/man-pages/man8/groupdel.8.html",
2085
+ "use_cases": [
2086
+ "Remove a group that is no longer needed: groupdel oldgroup",
2087
+ ],
2088
+ "gotchas": [
2089
+ "You cannot delete a group that is any user's primary group; change their primary group first",
2090
+ "Files owned by the deleted group will show a numeric GID instead of a group name",
2091
+ ],
2092
+ "related": ["groupadd", "groupmod"],
2093
+ "difficulty": "intermediate",
2094
+ "extra_flags": {},
2095
+ },
2096
+
2097
+ "groupmod": {
2098
+ "man_url": "https://man7.org/linux/man-pages/man8/groupmod.8.html",
2099
+ "use_cases": [
2100
+ "Rename a group: groupmod -n newname oldname",
2101
+ "Change a group's GID: groupmod -g 1050 groupname",
2102
+ ],
2103
+ "gotchas": [
2104
+ "Changing a GID does not update file ownership; files will show the old numeric GID. Run find / -gid OLD_GID -exec chgrp NEW_GROUP {} + to fix",
2105
+ ],
2106
+ "related": ["groupadd", "groupdel"],
2107
+ "difficulty": "intermediate",
2108
+ "extra_flags": {},
2109
+ },
2110
+
2111
+ "passwd": {
2112
+ "man_url": "https://man7.org/linux/man-pages/man1/passwd.1.html",
2113
+ "use_cases": [
2114
+ "Change your own password: passwd",
2115
+ "Set a password for a new user (as root): passwd newuser",
2116
+ "Lock an account to prevent login: passwd -l username",
2117
+ "Force a user to change password at next login: passwd -e username",
2118
+ ],
2119
+ "gotchas": [
2120
+ "passwd enforces password complexity policies; if a password is rejected, check /etc/security/pwquality.conf or PAM settings",
2121
+ "passwd -l only locks the password; SSH key auth still works. Use usermod -s /sbin/nologin for a full lockout",
2122
+ "passwd -d removes the password entirely, which may allow passwordless login depending on PAM configuration",
2123
+ ],
2124
+ "related": ["chpasswd", "usermod", "useradd"],
2125
+ "difficulty": "beginner",
2126
+ "extra_flags": {},
2127
+ },
2128
+
2129
+ "chpasswd": {
2130
+ "man_url": "https://man7.org/linux/man-pages/man8/chpasswd.8.html",
2131
+ "use_cases": [
2132
+ "Batch set passwords for multiple users: echo 'user1:pass1\\nuser2:pass2' | chpasswd",
2133
+ "Automated user provisioning in scripts: echo 'newuser:temppass' | chpasswd",
2134
+ ],
2135
+ "gotchas": [
2136
+ "Passwords passed on the command line or in files are visible in process listings and shell history; use secure input methods",
2137
+ "Without -e, chpasswd expects plain text passwords which it hashes; with -e, it expects pre-hashed passwords",
2138
+ ],
2139
+ "related": ["passwd", "useradd"],
2140
+ "difficulty": "intermediate",
2141
+ "extra_flags": {},
2142
+ },
2143
+
2144
+ "pwck": {
2145
+ "man_url": "https://man7.org/linux/man-pages/man8/pwck.8.html",
2146
+ "use_cases": [
2147
+ "Verify integrity of /etc/passwd and /etc/shadow after manual edits: pwck",
2148
+ "Run a read-only check without fixing anything: pwck -r",
2149
+ ],
2150
+ "gotchas": [
2151
+ "pwck may prompt to delete entries with errors; use -r first to review without changes",
2152
+ ],
2153
+ "related": ["grpck", "vipw", "passwd"],
2154
+ "difficulty": "advanced",
2155
+ "extra_flags": {},
2156
+ },
2157
+
2158
+ "grpck": {
2159
+ "man_url": "https://man7.org/linux/man-pages/man8/grpck.8.html",
2160
+ "use_cases": [
2161
+ "Verify integrity of /etc/group and /etc/gshadow: grpck",
2162
+ "Read-only integrity check: grpck -r",
2163
+ ],
2164
+ "gotchas": [
2165
+ "Like pwck, grpck may prompt to remove invalid entries; use -r first to preview",
2166
+ ],
2167
+ "related": ["pwck", "vigr", "groupmod"],
2168
+ "difficulty": "advanced",
2169
+ "extra_flags": {},
2170
+ },
2171
+
2172
+ "vipw": {
2173
+ "man_url": "https://man7.org/linux/man-pages/man8/vipw.8.html",
2174
+ "use_cases": [
2175
+ "Safely edit /etc/passwd with file locking: vipw",
2176
+ "Edit the shadow file: vipw -s",
2177
+ ],
2178
+ "gotchas": [
2179
+ "Always use vipw instead of directly editing /etc/passwd to prevent file corruption from concurrent access",
2180
+ "vipw validates syntax on save; if validation fails, it gives you a chance to fix errors before saving",
2181
+ ],
2182
+ "related": ["vigr", "pwck", "passwd"],
2183
+ "difficulty": "advanced",
2184
+ "extra_flags": {},
2185
+ },
2186
+
2187
+ "vigr": {
2188
+ "man_url": "https://man7.org/linux/man-pages/man8/vigr.8.html",
2189
+ "use_cases": [
2190
+ "Safely edit /etc/group with file locking: vigr",
2191
+ "Edit the shadow group file: vigr -s",
2192
+ ],
2193
+ "gotchas": [
2194
+ "Like vipw, always use vigr instead of directly editing /etc/group",
2195
+ ],
2196
+ "related": ["vipw", "grpck", "groupmod"],
2197
+ "difficulty": "advanced",
2198
+ "extra_flags": {},
2199
+ },
2200
+
2201
+ "getfacl": {
2202
+ "man_url": "https://man7.org/linux/man-pages/man1/getfacl.1.html",
2203
+ "use_cases": [
2204
+ "View ACL entries on a file: getfacl filename",
2205
+ "Audit ACLs recursively on a directory: getfacl -R /shared/",
2206
+ "Back up ACLs before making changes: getfacl -R /data > acl-backup.txt",
2207
+ ],
2208
+ "gotchas": [
2209
+ "A + sign in ls -l output after permissions indicates ACLs are set; use getfacl to see them",
2210
+ "The filesystem must be mounted with ACL support (most modern filesystems have this by default)",
2211
+ "Default ACLs on directories affect new files created inside them, not the directory itself",
2212
+ ],
2213
+ "related": ["setfacl", "chmod", "chown"],
2214
+ "difficulty": "intermediate",
2215
+ "extra_flags": {},
2216
+ },
2217
+
2218
+ "setfacl": {
2219
+ "man_url": "https://man7.org/linux/man-pages/man1/setfacl.1.html",
2220
+ "use_cases": [
2221
+ "Grant a specific user read access to a file: setfacl -m u:alice:r file.txt",
2222
+ "Set a default ACL so new files in a directory inherit permissions: setfacl -d -m g:developers:rwx /shared/",
2223
+ "Restore ACLs from a backup: setfacl --restore=acl-backup.txt",
2224
+ "Remove all ACLs from a file: setfacl -b file.txt",
2225
+ ],
2226
+ "gotchas": [
2227
+ "ACL entries require a mask entry that limits the effective permissions; use setfacl -m m::rwx to ensure the mask does not restrict your ACL entries",
2228
+ "Copying files may not preserve ACLs unless you use cp -a or rsync -A",
2229
+ "The ACL mask is recalculated when you add or modify ACL entries, which can inadvertently restrict existing entries",
2230
+ ],
2231
+ "related": ["getfacl", "chmod", "chown"],
2232
+ "difficulty": "intermediate",
2233
+ "extra_flags": {},
2234
+ },
2235
+
2236
+ "umask": {
2237
+ "man_url": "https://man7.org/linux/man-pages/man2/umask.2.html",
2238
+ "use_cases": [
2239
+ "Check the current umask: umask (octal) or umask -S (symbolic)",
2240
+ "Set restrictive default permissions for new files: umask 077 (only owner can read/write/execute)",
2241
+ "Set the umask in shell profile for consistent permissions across sessions",
2242
+ ],
2243
+ "gotchas": [
2244
+ "umask subtracts from the maximum permissions (666 for files, 777 for directories); umask 022 means new files get 644 and directories get 755",
2245
+ "umask only affects newly created files; it does not change permissions on existing files",
2246
+ "umask is per-process and inherited by child processes; setting it in one terminal does not affect others",
2247
+ ],
2248
+ "related": ["chmod", "getfacl", "setfacl"],
2249
+ "difficulty": "intermediate",
2250
+ "extra_flags": {},
2251
+ },
2252
+
2253
+ "chgrp": {
2254
+ "man_url": "https://man7.org/linux/man-pages/man1/chgrp.1.html",
2255
+ "use_cases": [
2256
+ "Change group ownership of a shared directory: chgrp developers /shared/project/",
2257
+ "Recursively change group for all files: chgrp -R webteam /var/www/",
2258
+ ],
2259
+ "gotchas": [
2260
+ "You must be a member of the target group (or root) to change a file's group",
2261
+ "chgrp does not change the owner; use chown user:group to change both at once",
2262
+ ],
2263
+ "related": ["chown", "chmod", "groups"],
2264
+ "difficulty": "beginner",
2265
+ "extra_flags": {
2266
+ "-v": "Verbose output showing each change",
2267
+ "--reference": "Set group to match another file",
2268
+ },
2269
+ },
2270
+ }