Linux Commands for Process Management (ps, top, kill)

Illustration showing Linux process management: terminal displaying ps output and top monitor, arrows to a kill command terminating a process, icons for CPU, memory, PID. Live view.

Linux Commands for Process Management (ps, top, kill)
SPONSORED

Sponsor message — This article is made possible by Dargslan.com, a publisher of practical, no-fluff IT & developer workbooks.

Why Dargslan.com?

If you prefer doing over endless theory, Dargslan’s titles are built for you. Every workbook focuses on skills you can apply the same day—server hardening, Linux one-liners, PowerShell for admins, Python automation, cloud basics, and more.


In the world of system administration and everyday computing, understanding how your machine allocates resources can mean the difference between a smoothly running system and one that grinds to a halt. Whether you're troubleshooting a frozen application, investigating unexpected system slowdowns, or simply curious about what's happening under the hood of your Linux machine, process management commands are your essential toolkit. These tools give you visibility into the heartbeat of your operating system—the processes that consume memory, processor time, and other critical resources.

Process management in Linux refers to the suite of commands and techniques used to monitor, control, and manipulate running programs and system tasks. Unlike graphical task managers you might be familiar with from other operating systems, Linux provides powerful command-line utilities that offer granular control and detailed insights into system behavior. This article explores three fundamental commands—ps, top, and kill—that form the cornerstone of process management for administrators and power users alike.

Throughout this comprehensive guide, you'll gain practical knowledge about identifying processes, interpreting system resource usage, and taking corrective action when programs misbehave. We'll examine the syntax and options for each command, explore real-world scenarios where they prove invaluable, and provide tables that clarify their most useful parameters. By the end, you'll have the confidence to navigate your system's process landscape with precision and authority.

Understanding Linux Processes and Their Lifecycle

Every action on a Linux system, from opening a text editor to running a web server, creates one or more processes. A process is essentially an instance of a program in execution, complete with its own memory space, system resources, and unique identifier. When you launch an application, the operating system assigns it a Process ID (PID), which serves as its fingerprint throughout its lifetime. Understanding this fundamental concept is crucial because all process management commands revolve around identifying and manipulating these PIDs.

Processes exist in various states throughout their lifecycle. A process might be running (actively using CPU time), sleeping (waiting for an event or resource), stopped (suspended by a signal), or zombie (completed but not yet cleaned up by its parent process). Each state provides information about what the process is doing and why it might be consuming resources. The commands we'll explore give you windows into these states, allowing you to diagnose problems and make informed decisions about system management.

"Understanding process states is not just about knowing what your system is doing—it's about predicting what it will do next and preventing problems before they cascade into system-wide failures."

Linux processes are organized hierarchically, with each process (except the init process) having a parent. This parent-child relationship matters because signals sent to parent processes can affect their children, and understanding this hierarchy helps you make surgical interventions rather than broad system changes. When you examine processes, you'll notice Parent Process IDs (PPIDs) that trace this lineage, revealing how applications spawn subprocesses and how system services are structured.

The ps Command: Snapshot of Process Information

The ps command provides a snapshot of currently running processes at the moment you execute it. Unlike monitoring tools that update continuously, ps captures a single moment in time, making it perfect for scripting, logging, and situations where you need precise information without the overhead of continuous monitoring. This command has been part of Unix-like systems for decades, and its flexibility comes from an extensive array of options that let you customize exactly what information you see and how it's formatted.

Basic ps Syntax and Common Options

At its simplest, typing ps without any options shows processes associated with your current terminal session—usually just your shell and the ps command itself. This minimal output isn't particularly useful for system-wide monitoring, which is why ps shines when combined with options that expand its scope. The command supports three different styles of options: Unix options (preceded by a dash), BSD options (no dash), and GNU long options (double dash). This historical quirk can be confusing, but understanding a few key combinations will cover most use cases.

Command Description Typical Use Case
ps aux Shows all processes for all users with detailed information Getting a comprehensive system overview
ps -ef Full-format listing of all processes Viewing parent-child process relationships
ps -u username Shows processes owned by a specific user Troubleshooting user-specific issues
ps -C processname Shows processes by command name Finding all instances of a specific program
ps --forest Displays process hierarchy as a tree Understanding process parent-child relationships

The ps aux command deserves special attention as it's probably the most frequently used variant. The 'a' option shows processes for all users, 'u' provides user-oriented format with additional details like CPU and memory usage, and 'x' includes processes not attached to a terminal. The output includes columns for USER, PID, CPU percentage, memory percentage, virtual memory size, resident set size, terminal, process state, start time, CPU time, and the command that launched the process.

Interpreting ps Output

When you run ps with detailed options, you'll see columns that require interpretation. The %CPU column shows the percentage of CPU time used by the process since it started—not instantaneous usage. Similarly, %MEM represents the ratio of the process's resident set size to physical memory. The STAT column uses letter codes to indicate process state: R for running, S for sleeping, D for uninterruptible sleep (usually I/O), T for stopped, and Z for zombie processes. Additional characters modify these states, such as '<' for high priority or 'N' for low priority.

"The true power of ps lies not in seeing what's running, but in filtering and formatting that information to answer specific questions about system behavior."

You can customize ps output using the -o option followed by column specifications. This allows you to create focused views that show only the information relevant to your current task. For example, ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem displays processes sorted by memory usage, showing only PID, parent PID, command, memory percentage, and CPU percentage. This customization capability makes ps invaluable for scripting and automated monitoring.

Practical ps Command Examples

  • 🔍 Finding resource-hungry processes: Use ps aux --sort=-%cpu | head -10 to see the top ten CPU consumers, or replace %cpu with %mem for memory hogs
  • 🔍 Locating processes by name: Combine with grep: ps aux | grep nginx to find all nginx-related processes
  • 🔍 Viewing process hierarchy: Execute ps -ejH or ps axjf to see parent-child relationships in a tree format
  • 🔍 Monitoring specific user activity: Run ps -u apache -o pid,cmd,%cpu,%mem to track what the apache user is running
  • 🔍 Checking process start times: Use ps -eo pid,lstart,cmd to see when each process began execution

The top Command: Real-Time Process Monitoring

While ps gives you a snapshot, top provides a continuously updating dashboard of system activity. This interactive command refreshes its display at regular intervals (typically every three seconds), showing you how processes consume resources over time. The top command has been the go-to tool for system administrators who need to watch system behavior as it unfolds, making it indispensable for diagnosing performance issues, identifying runaway processes, and understanding system load patterns.

Understanding the top Interface

When you launch top, the screen divides into two main sections. The upper section displays system-wide statistics including uptime, number of users, load averages, task counts broken down by state, CPU usage percentages, and memory/swap utilization. The lower section shows a dynamically sorted list of processes, defaulting to CPU usage order. This dual-view approach lets you correlate individual process behavior with overall system health, making it easier to identify when a single process is impacting system-wide performance.

The load average numbers in the top line deserve explanation. These three values represent the average number of processes waiting for CPU time over the last 1, 5, and 15 minutes. On a single-core system, a load average of 1.0 means the CPU is fully utilized; on a quad-core system, full utilization would show as 4.0. Load averages above your core count indicate processes are waiting for CPU time, while numbers significantly below suggest idle capacity. Watching how these values trend gives you insight into whether performance issues are temporary spikes or sustained problems.

Interactive Commands Within top

One of top's strengths is its interactivity. While it's running, you can press various keys to change what you see and how information is sorted. Pressing 'M' sorts processes by memory usage, 'P' sorts by CPU usage, and 'T' sorts by running time. The 'k' key allows you to send signals to processes (we'll cover this more in the kill section), while 'r' lets you renice processes to change their priority. Pressing '1' toggles between showing aggregate CPU statistics and per-core breakdowns, which is particularly useful on multi-core systems.

"Real-time monitoring isn't about watching numbers change—it's about recognizing patterns that indicate emerging problems before they become critical failures."
Key Action Why It Matters
M Sort by memory usage Quickly identify memory leaks or excessive memory consumption
P Sort by CPU usage Find processes causing high CPU load
k Kill a process Terminate problematic processes without leaving top
r Renice a process Adjust process priority to manage resource allocation
f Choose display fields Customize which process attributes are visible
d Change refresh interval Adjust update frequency for your monitoring needs
u Filter by user Focus on processes belonging to specific users
c Toggle command line display See full command paths versus just program names

Advanced top Usage and Alternatives

You can start top with command-line options to customize its initial behavior. The -u username option filters to show only processes owned by that user, while -p PID monitors specific processes. The -d option sets the refresh interval in seconds, useful when you want more frequent updates than the default. For batch mode operation (useful in scripts), use -b combined with -n to specify the number of iterations before exiting.

Modern Linux distributions often include htop, an enhanced alternative to top with a more colorful, user-friendly interface. It provides mouse support, horizontal and vertical scrolling, and a tree view of processes. While not part of the standard toolkit covered here, htop offers similar functionality with improved usability. Another alternative is atop, which includes historical data collection and more detailed disk I/O statistics. However, the traditional top command remains ubiquitous and is guaranteed to be present on virtually any Linux system you encounter.

"The difference between a novice and an expert isn't just knowing which commands to run—it's understanding what the output tells you about your system's health and knowing which metrics matter for your specific situation."

The kill Command: Managing Process Lifecycle

Despite its aggressive name, the kill command doesn't necessarily terminate processes—it sends signals to them. Signals are software interrupts that tell processes to perform specific actions, from gracefully shutting down to immediately terminating or reloading configuration files. Understanding kill and its related commands gives you precise control over process behavior, allowing you to manage misbehaving applications, restart services cleanly, and coordinate process communication.

Signal Types and Their Purposes

Linux supports dozens of signals, each identified by a number and a name. The most commonly used signals include SIGTERM (15), which politely asks a process to terminate and allows it to clean up resources; SIGKILL (9), which immediately terminates a process without cleanup; SIGHUP (1), traditionally meaning "hangup" but often used to tell daemons to reload configuration; and SIGSTOP (19), which pauses a process without terminating it. The default signal when you don't specify one is SIGTERM, reflecting the general principle that you should try graceful shutdown before resorting to forceful termination.

The distinction between SIGTERM and SIGKILL is crucial. When you send SIGTERM, the process receives notification and can execute shutdown procedures—closing files, saving state, releasing locks, and notifying other processes. This clean shutdown prevents data corruption and resource leaks. SIGKILL, however, bypasses the process entirely, telling the kernel to immediately reclaim all resources. While this guarantees termination, it can leave files corrupted, locks unreleased, and dependent processes in inconsistent states. Always try SIGTERM first, reserving SIGKILL for processes that refuse to respond.

Basic kill Command Syntax

The fundamental syntax is kill [signal] PID. If you omit the signal, SIGTERM is sent. You can specify signals by number (kill -9 1234), by name with SIG prefix (kill -SIGKILL 1234), or by name without prefix (kill -KILL 1234). To see all available signals, run kill -l. You can target multiple processes by listing their PIDs separated by spaces, and you can use negative numbers to signal entire process groups.

  • Graceful termination: kill 1234 or kill -15 1234 sends SIGTERM to process 1234
  • Forced termination: kill -9 1234 immediately kills process 1234 (use as last resort)
  • Reloading configuration: kill -HUP 1234 tells many daemons to reload their config files
  • Pausing execution: kill -STOP 1234 freezes process 1234 without terminating it
  • Resuming execution: kill -CONT 1234 unfreezes a stopped process

While kill requires you to know the exact PID, killall and pkill let you target processes by name. The killall command sends signals to all processes matching a specific command name: killall firefox would terminate all Firefox processes. Be cautious with killall, especially on systems where you don't know what's running, as you might unintentionally affect critical processes with common names.

The pkill command offers more sophisticated pattern matching, using regular expressions to select processes. It also supports options like -u to target processes by user, -t to target by terminal, and -f to match against the full command line rather than just the process name. For example, pkill -u apache would send SIGTERM to all processes owned by the apache user, while pkill -f "python.*script.py" would match Python processes running a specific script.

"Knowing when to use SIGTERM versus SIGKILL is like knowing when to ask politely versus when to flip the circuit breaker—both have their place, but choosing wrongly can cause more problems than you solve."

Safe Process Termination Strategies

When dealing with unresponsive processes, follow a escalating approach. First, try SIGTERM to allow graceful shutdown. Wait several seconds to give the process time to clean up. If it persists, check whether it's actually stuck or just taking time to shut down properly. You can use ps or top to monitor whether the process state changes. If the process remains after a reasonable timeout (typically 10-30 seconds depending on what it does), then escalate to SIGKILL. This methodical approach minimizes the risk of data loss and system instability.

For critical services, consider checking whether the service manager (systemd, init, etc.) provides shutdown commands rather than using kill directly. Service managers often have built-in logic for graceful restarts and dependency management. For example, systemctl stop service-name might be preferable to killing individual processes because it handles the entire service lifecycle correctly. However, when a process is truly frozen and not responding to management commands, direct signal sending becomes necessary.

Combining Commands for Powerful Process Management

The real power of these commands emerges when you combine them with pipes, filters, and shell scripting. You might use ps to identify problematic processes, pipe the output through grep and awk to extract PIDs, then pass those PIDs to kill. This command chaining allows you to automate complex process management tasks and create custom monitoring solutions tailored to your specific needs.

Practical Command Combinations

Finding and terminating processes by name without using killall: ps aux | grep processname | grep -v grep | awk '{print $2}' | xargs kill. This pipeline lists all processes, filters to those matching the name, removes the grep command itself from results, extracts the PID column, and passes those PIDs to kill. While more complex than killall, it gives you visibility into what's being terminated and allows you to add additional filtering criteria.

Monitoring specific processes over time: watch -n 2 'ps aux | grep [p]rocessname'. The watch command repeatedly executes the ps/grep combination every 2 seconds, giving you a continuously updating view of specific processes. The bracket notation [p]rocessname is a trick to prevent grep from matching itself. This approach provides focused monitoring without the full overhead of top.

Identifying and addressing zombie processes: ps aux | grep 'Z' shows zombie processes (those with Z in the STAT column). Zombies can't be killed directly because they're already dead—they're waiting for their parent process to acknowledge their termination. You typically need to kill or restart the parent process, which you can identify using the PPID column from ps -ef.

"The command line isn't just a tool—it's a language for expressing your intentions to the system, and like any language, fluency comes from understanding not just vocabulary but syntax, idioms, and context."

Scripting Process Management Tasks

Shell scripts can automate routine process management. A simple monitoring script might check if a critical service is running and restart it if necessary. You could use pgrep -x processname to check for existence (it returns the PID if found, nothing if not), then use the exit code to decide whether to start the service. More sophisticated scripts might log process resource usage over time, alert administrators when thresholds are exceeded, or implement custom restart logic with exponential backoff for flapping services.

When scripting process termination, always include proper error handling. Check whether kill commands succeed, verify that processes actually terminate, and implement timeouts to prevent scripts from hanging indefinitely. A robust termination script might try SIGTERM, wait with a timeout, check if the process still exists, then escalate to SIGKILL only if necessary. This defensive programming approach prevents scripts from becoming part of the problem rather than the solution.

Performance Considerations and Best Practices

Understanding the performance impact of process management commands helps you use them effectively without inadvertently causing the problems you're trying to solve. The ps command is relatively lightweight because it reads process information from the /proc filesystem without continuous monitoring. However, running ps with extensive filtering and sorting on systems with thousands of processes can consume noticeable CPU time. If you need to run ps frequently, consider limiting the output with specific user or process filters rather than processing the entire process table.

The top command continuously consumes CPU cycles to update its display. On systems already under heavy load, running top with a short refresh interval can exacerbate performance problems. If you're monitoring a struggling system, consider increasing the refresh interval with the -d option or using ps with watch instead. When running top in production environments, be mindful that the act of observation affects what you're observing—a principle familiar from quantum mechanics that applies equally to system administration.

Security Implications of Process Management

Process management commands reveal information about system activity that might be sensitive. Regular users can see their own processes but typically can't see detailed information about processes owned by others or send signals to them. This privilege separation prevents users from interfering with each other's work or with system services. However, the root user has unrestricted access, making these commands powerful tools for administration but also potential vectors for system disruption if misused.

When granting users elevated privileges through sudo, carefully consider which process management commands they need. Allowing unrestricted kill access means users can terminate critical system services. Instead, configure sudo to permit specific actions like restarting particular services. Some organizations create wrapper scripts that provide controlled process management capabilities without exposing the full power of these commands. This principle of least privilege reduces the risk of accidental or malicious system disruption.

Troubleshooting Common Issues

When processes won't terminate even with SIGKILL, they're typically stuck in uninterruptible sleep (D state), usually waiting for I/O operations to complete. This often indicates hardware problems, filesystem issues, or kernel bugs. These processes can't be killed because they're waiting for the kernel to complete an operation, and interrupting them could corrupt data. The solution usually involves fixing the underlying issue (remounting a filesystem, resetting hardware, etc.) rather than forcing process termination.

High load averages without corresponding high CPU usage often indicate I/O bottlenecks. Processes waiting for disk or network I/O count toward load average but don't show high CPU percentages. In these cases, tools like iostat or iotop provide better insight than CPU-focused process monitoring. Understanding this distinction prevents you from chasing CPU optimization when the real problem lies elsewhere in the system.

Process Priority and Nice Values

Linux uses priority values to determine which processes get CPU time when multiple processes compete for resources. The nice value ranges from -20 (highest priority) to 19 (lowest priority), with 0 being the default. Despite the counterintuitive naming (higher nice values mean lower priority), the concept is that "nicer" processes yield more readily to others. Regular users can only increase nice values (lower priority) for their processes, while root can set any value.

You can launch processes with specific nice values using the nice command: nice -n 10 command starts the command with a nice value of 10. To change the priority of running processes, use renice: renice -n 5 -p 1234 sets process 1234's nice value to 5. Within top, pressing 'r' lets you renice processes interactively. Adjusting process priority is useful for background tasks that shouldn't interfere with interactive work or for ensuring critical services get preferential CPU access during high load.

Understanding System Load and Resource Constraints

Process management becomes critical when systems approach resource limits. CPU saturation occurs when load average significantly exceeds the number of cores, indicating processes are waiting for CPU time. Memory pressure happens when physical RAM fills up and the system relies heavily on swap space, causing dramatic performance degradation. Understanding these constraints helps you interpret process monitoring output and take appropriate action—whether that means terminating resource-hungry processes, adjusting priorities, or adding hardware capacity.

The relationship between process count and system performance isn't linear. A system might handle hundreds of sleeping processes with minimal impact but struggle with a dozen CPU-intensive processes competing for limited cores. Context switching—the overhead of the kernel switching between processes—becomes significant when many processes actively compete for CPU time. This is why a few well-behaved processes often perform better than many poorly-behaved ones, even if total resource consumption is similar.

Process Management in Modern Container Environments

Container technologies like Docker introduce new considerations for process management. Within a container, processes appear with their own PID namespace, so PID 1 inside a container might be PID 5432 on the host. When using ps or top on the host system, you'll see all container processes, but from inside a container, you only see processes within that container. This isolation is intentional and provides security benefits, but it requires understanding the relationship between host and container process spaces when troubleshooting.

Container orchestration systems like Kubernetes add another layer of abstraction. Processes run within containers, which run within pods, which are scheduled across nodes. Traditional process management commands still work at the node level, but you typically interact with containers through higher-level commands like docker exec or kubectl exec. However, when debugging node-level issues or investigating resource contention, the fundamental ps, top, and kill commands remain relevant and valuable.

Monitoring Strategies for Different Scenarios

Development environments benefit from interactive monitoring with top or htop, where you can quickly identify which test runs or compilation jobs are consuming resources. The interactive nature lets you drill down into specific processes and make immediate adjustments. In these environments, the overhead of continuous monitoring is acceptable because you're actively investigating behavior.

Production environments require different approaches. Continuous interactive monitoring isn't practical, and the overhead isn't justified. Instead, use periodic ps snapshots logged for later analysis, or implement proper monitoring solutions that aggregate metrics over time. When issues arise, you can use top for immediate investigation, but your primary monitoring should be automated and lightweight. Many organizations use monitoring agents that collect process metrics and ship them to centralized systems for analysis and alerting.

Advanced Signal Handling and Process Communication

Beyond basic termination, signals enable sophisticated inter-process communication. User-defined signals SIGUSR1 and SIGUSR2 allow applications to implement custom behaviors. Some daemons use SIGUSR1 to toggle debug logging, while others use it to trigger status dumps. Reading application documentation reveals what signals they respond to and what behaviors those signals trigger. This knowledge transforms kill from a blunt instrument into a precise communication tool.

Signal handling in shell scripts allows you to create robust applications that clean up properly when interrupted. The trap command lets scripts catch signals and execute cleanup code before exiting. This is particularly important for scripts that create temporary files, acquire locks, or manage background processes. Proper signal handling prevents resource leaks and ensures scripts leave the system in a consistent state even when terminated unexpectedly.

Process Accounting and Historical Analysis

While ps and top show current state, process accounting systems like acct or psacct track historical process execution. These systems log every process that runs, recording start time, end time, resource usage, and exit status. This historical data proves invaluable for capacity planning, security auditing, and troubleshooting intermittent issues. When a problem occurs at 3 AM and you investigate in the morning, process accounting logs show exactly what was running when the issue occurred.

Modern systems often use systemd's journal for process tracking, which includes process lifecycle events, resource usage, and log messages in a unified format. The journalctl command can filter logs by process, time range, or other criteria, providing rich context for process behavior. Combining traditional process management commands with journal analysis gives you both real-time visibility and historical perspective.

What's the difference between ps aux and ps -ef?

Both commands show all processes on the system, but they use different option styles and output formats. The ps aux command uses BSD-style options (no leading dash) and displays user-oriented output with columns for CPU percentage, memory percentage, and other resource metrics. The ps -ef command uses Unix-style options (with dash) and shows a full-format listing that emphasizes parent-child relationships with PPID (Parent Process ID) prominently displayed. For most purposes, they provide similar information, and choosing between them is largely a matter of personal preference and which output format you find more readable.

How do I find which process is using the most memory?

Use ps aux --sort=-%mem | head -n 10 to see the top ten memory-consuming processes, with the highest consumer listed first. The --sort=-%mem option sorts by memory percentage in descending order (the minus sign indicates descending). Alternatively, run top and press M to sort by memory usage interactively. The %MEM column shows what percentage of total physical memory each process is using. For more detailed memory analysis including shared memory and different memory types, consider using commands like pmap or reading the process's status file directly from /proc/[pid]/status.

Why won't my process die even after using kill -9?

Processes that survive SIGKILL are typically in uninterruptible sleep (D state), meaning they're waiting for a kernel operation to complete—usually I/O operations like reading from disk or network. The kernel puts processes in this state when interrupting them could cause data corruption or system instability. These processes cannot be killed until the operation they're waiting for completes or fails. Common causes include failing hard drives, disconnected network storage, or kernel bugs. Check the process state with ps aux (look for D in the STAT column). Solutions typically involve fixing the underlying issue: remounting filesystems, resetting hardware, checking network connectivity, or as a last resort, rebooting the system.

What do the different load average numbers mean?

Load average shows three numbers representing the average number of processes in the run queue (running or waiting to run) over the last 1, 5, and 15 minutes. On a single-core system, a load of 1.0 means the CPU is fully utilized; 0.5 means it's half utilized; and 2.0 means processes are waiting (on average, one process is waiting while one runs). On multi-core systems, multiply these thresholds by the number of cores—a quad-core system at full utilization shows load average around 4.0. The three time periods help you understand trends: if all three numbers are similar, load is stable; if the 1-minute average is much higher than the 15-minute average, load is increasing; if it's lower, load is decreasing. Load average includes processes waiting for I/O, not just CPU, so high load with low CPU usage often indicates I/O bottlenecks.

How can I monitor a specific process continuously?

Use top -p PID to monitor a specific process by its PID, which updates every few seconds showing resource usage changes. For multiple specific processes, list them separated by commas: top -p 1234,5678,9012. Alternatively, use watch -n 2 'ps -p PID -o pid,cmd,%cpu,%mem' to execute ps every 2 seconds showing just the information you want. For long-term monitoring with logging, create a script that periodically runs ps and appends output to a file: while true; do ps -p PID -o pid,%cpu,%mem >> logfile; sleep 60; done. For production systems, consider proper monitoring solutions like Prometheus or Nagios that can track process metrics over time, generate alerts, and create visualizations of historical trends.

What's the difference between SIGTERM and SIGKILL?

SIGTERM (signal 15) is a polite request for a process to terminate. The process receives this signal and can execute shutdown procedures—closing files, saving state, releasing resources, and notifying other processes. This clean shutdown prevents data corruption and resource leaks. SIGKILL (signal 9) bypasses the process entirely, telling the kernel to immediately terminate it without giving it any opportunity to clean up. SIGKILL guarantees termination but can leave files corrupted, locks unreleased, and dependent processes in inconsistent states. Best practice is always trying SIGTERM first (it's the default when you run kill without specifying a signal), waiting several seconds for clean shutdown, and only escalating to SIGKILL if the process refuses to terminate. Some processes catch SIGTERM and ignore it or handle it specially, but no process can catch or ignore SIGKILL.

How do I see what files a process has open?

Use the lsof command (list open files) with the -p option: lsof -p PID shows all files, network connections, and other file descriptors that process has open. This is invaluable for troubleshooting issues like "file in use" errors or investigating what resources a process is accessing. You can also use ls -l /proc/PID/fd/ to see file descriptors directly from the proc filesystem. For network connections specifically, netstat -p or ss -p show which processes have which network sockets open. Understanding what files a process has open helps diagnose permission issues, resource leaks (processes holding too many file descriptors), and dependency problems.

Can I change a process's priority after it's started?

Yes, use the renice command to change a running process's nice value (priority). The syntax is renice -n NICE_VALUE -p PID, for example renice -n 10 -p 1234 sets process 1234's nice value to 10 (lower priority). Regular users can only increase nice values (decrease priority) for their own processes, making them "nicer" to other processes. The root user can set any nice value and can change priorities for any process. Within top, you can also press r, enter the PID, and specify a new nice value. Changing priority is useful when you have background tasks that shouldn't interfere with interactive work, or when you need to ensure critical services get preferential CPU access during high load. Remember that nice values only affect CPU scheduling—they don't directly control memory usage or I/O priority.