Linux Commands Every Developer Needs to Know
1. Overview
Every developer has SSH’d into a server, debugged in a terminal, or deployed an app, then fumbled around looking for the right command. This article compiles the most commonly used Linux commands in daily work: file management, searching, text processing, process monitoring, network checking, and log viewing. After reading, you’ll have a “survival kit” of commands to debug quickly without needing to Google the same thing every time.
I’ll use bash on Ubuntu/Debian as the main example, though these commands are almost identical across all distros.
2. File and Directory Operations
mkdir -p ~/projects/order-service/src/main/java
cd ~/projects/order-service
touch application.properties
ls -la
mkdir -pcreates the entire directory tree, doesn’t complain if the directory already exists.touchcreates an empty file (or updates timestamp if it exists).ls -lalists all files (including hidden ones like.env,.git) with permissions, owner, size.
drwxr-xr-x 3 nonla nonla 4096 Oct 5 10:00 .
-rw-r--r-- 1 nonla nonla 0 Oct 5 10:00 application.properties
Some move/delete commands that need caution:
cp -r src/ src-backup/ # recursive copy directory
mv OrderService.java OrderServiceImpl.java # rename or move
rm -rf target/ # recursive delete, no confirmation
Note:
rm -rfhas no recycle bin, deletion is permanent. Always verify your path withpwdbefore running, especially when copy-pasting commands from elsewhere.
3. Finding with find and grep
3.1. find — search files by criteria
find . -name "*.java" -newer pom.xml
This finds all .java files modified after pom.xml — useful to see which files changed before committing.
find . -type f -size +10M
Find files larger than 10MB, commonly used to clean up logs or build artifacts consuming space.
3.2. grep — search content in files
grep -rn "PaymentService" --include="*.java" src/
-rsearches recursively through subdirectories.-nprints with line numbers.--includerestricts to only.javafiles, avoiding searching intarget/.
src/main/java/com/nonla/OrderController.java:15: private final PaymentService paymentService;
Combine grep with find through a pipe for more complex filtering:
find . -name "*.log" | xargs grep -l "OutOfMemoryError"
xargs passes the file list from find to grep -l (only prints filenames containing the pattern, not the content).
4. Text Processing with awk, sed, cut
This group of commands is “log-eating” — extremely powerful when you need to extract data from verbose output.
cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -5
awk '{print $1}'takes the first column (usually IP) of each log line.sort | uniq -cgroups and counts occurrences.sort -rnsorts descending by count,head -5shows top 5.
152 192.168.1.10
98 10.0.0.5
47 172.16.0.3
This is the fastest way to find which IP made the most requests without writing a script.
sed replaces text directly in a file:
sed -i 's/spring.profiles.active=dev/spring.profiles.active=prod/' application.properties
-i edits the file in-place. For extra safety, use sed -i.bak '...' to auto-create a .bak backup file.
cut extracts columns by delimiter, lighter than awk when you just need one simple column:
cat /etc/passwd | cut -d: -f1 | head -3
5. Process and Resource Monitoring
ps aux | grep java
Prints all processes, filters for lines containing java — quick way to see if your Spring Boot app is running and what its PID is.
nonla 12345 2.1 5.3 2345678 432100 ? Sl 10:00 0:15 java -jar order-service.jar
The second column is the PID. Use this PID to kill or inspect further:
kill -15 12345 # send SIGTERM, allows app graceful shutdown
kill -9 12345 # force kill, only when -15 doesn't work
Note:
kill -9doesn’t let the app run shutdown hooks (like closing connection pools, flushing logs). Always try-15first.
View resource usage in real-time:
top -o %MEM
-o %MEM sorts processes by highest memory usage — useful when suspecting a memory leak. For a nicer interface, install htop.
Check disk:
df -h
du -sh /var/log/*
df -h shows each partition’s space (human-readable). du -sh shows how much each subdirectory in /var/log uses — critical when the server says “no space left on device”.
6. Network and Port Checking
ss -tulnp | grep 8080
ssreplaces the oldnetstat, much faster.-tTCP,-uUDP,-llistening,-nnumeric (don’t resolve DNS),-pinclude process.
tcp LISTEN 0 128 0.0.0.0:8080 0.0.0.0:* users:(("java",pid=12345,fd=45))
Know immediately that port 8080 is held by Java process PID 12345 — very useful when you hit Address already in use.
Quickly test an API with curl:
curl -s -X POST http://localhost:8080/api/orders \
-H "Content-Type: application/json" \
-d '{"customerId":1,"amount":99.5}'
-s silent (hide progress bar), -X POST sets method, -d sets JSON body. Add -i if you want to see response headers too.
Use lsof when you need to know exactly which files/sockets a process has open:
lsof -i :8080
7. File Permissions
chmod +x deploy.sh
chown nonla:nonla application.properties
chmod 640 .env
chmod +xmakes a script executable.chown user:groupchanges owner — usually needssudoif the file belongs to another user.chmod 640means owner read/write (6), group read-only (4), others none (0) — standard for sensitive files like.env.
-rw-r----- 1 nonla nonla 128 Oct 5 10:00 .env
Note: never
chmod 777in production. That’s the fastest way to let every user on the machine read/modify your sensitive files.
8. Compression and Decompression
tar -czvf order-service.tar.gz order-service/
tar -xzvf order-service.tar.gz -C /opt/apps/
-ccreates archive,-xextracts,-zuses gzip,-vverbose,-fspecifies filename.-Cwhen extracting, specifies target directory instead of extracting to current directory.
When deploying, combine with scp or rsync to push files to a server:
scp order-service.tar.gz user@10.0.0.5:/opt/apps/
rsync -avz --progress target/*.jar user@10.0.0.5:/opt/apps/
rsync only transfers changed data (delta transfer), much faster than scp when updating large files multiple times.
9. Viewing Logs in Real-Time
tail -f /var/log/order-service/app.log
-f (follow) keeps the terminal open and prints new lines as the file grows — a must-know command for production debugging.
Filter logs by pattern while tailing:
tail -f app.log | grep --line-buffered "ERROR"
--line-buffered is necessary because grep normally buffers by block, without this flag output can be delayed when piping with tail -f.
If your app runs under systemd, use journalctl instead of manually finding log files:
journalctl -u order-service -f --since "10 minutes ago"
-u specifies the service unit, -f follows, --since limits time — avoid reading millions of old log lines.
10. Running Linux Commands from Java
Sometimes you need to call shell commands directly from Java code, for example checking disk space before writing a large file:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;
public class ShellRunner {
public static String run(List<String> command) throws Exception {
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
Process process = builder.start();
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String output = reader.lines().reduce("", (a, b) -> a + b + "\n");
process.waitFor();
return output;
}
}
}
ProcessBuildertakes a list of arguments (not a hand-glued command string, avoiding shell injection).redirectErrorStream(true)merges stderr into stdout so you read a single stream.process.waitFor()blocks the current thread until the child process exits.
Test with JUnit 5 + AssertJ:
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class ShellRunnerTest {
@Test
void shouldReturnCurrentDirectoryListing() throws Exception {
String output = ShellRunner.run(List.of("ls", "-la"));
assertThat(output).contains("total");
}
}
This test runs ls -la for real on the system and checks if the output contains “total” (the first line ls -la always prints showing total blocks) — confirming ProcessBuilder really calls the shell command.
Note: calling shell commands from Java production code is a double-edged sword — easy to depend on OS, hard to test, and injection risk if arguments come from user input. Use only for internal tools or operational scripts, avoid for core business logic.
11. Common Mistakes
- Running
rm -rfwith an empty environment variable, e.g.rm -rf $DIR/*when$DIRisn’t set — deletes the wrong directory. Always useset -uin scripts or check variables first. - Forgetting
sudowhen you need root permission, resulting in vaguePermission deniederrors — check withls -lafirst before blaming the app. - Habitually using
kill -9, so Spring Boot can’t close connection pools in time, causing database leaks. - Piping
grepaftertail -fbut forgetting--line-buffered, thinking the logs aren’t flowing when they’re actually buffered. - Running
chmod 777to “quickly get past permission errors” — creates security holes, especially dangerous with.envor SSH key files.
12. Conclusion
The commands in this article — find, grep, awk/sed, ps/kill, ss/curl, tar, tail -f, journalctl — are the minimum toolkit to debug on your own without waiting for the DevOps team. Being good with them doesn’t mean remembering all the flags, just knowing which command solves what problem and looking up man when you need details. Terminal remains the fastest debugging tool, even with all the Grafana, Kibana, and APM tools around.