Linux shell дээр процесс удирдах

Дусал нэвтэрхий толь-с
15:45, 9 Хоёрдугаар сар 2022-ий байдлаарх Almas (Яриа | оруулсан хувь нэмэр) хэрэглэгчийн хийсэн залруулга
(ялгаа) ←Хуучны засвар | Одоогийн засвар (ялгаа) | Дараагийн засвар→ (ялгаа)

How To Use ps, kill, and nice to Manage Processes in Linux

Янзалж орчуулах шаардлагатай. Болж өгвөл базах хэрэгтэй.

Introduction

A Linux server, like any modern computer, runs multiple applications. These are referred to and managed as individual processes.

While Linux will handle the low-level, behind-the-scenes management in a process’s life-cycle – i.e., startup, shutdown, memory allocation, and so on – you will need a way of interacting with the operating system to manage them from a higher level.

In this guide, you will learn some fundamental aspects of process management. Linux provides a number of standard, built-in tools for this purpose.

You will explore these ideas in a Ubuntu 20.04 environment, but any modern Linux distribution will operate in a similar way. Step 1 – How To View Running Processes in Linux

You can see all of the processes running on your server by using the top command:

   top

Output top - 15:14:40 up 46 min, 1 user, load average: 0.00, 0.01, 0.05 Tasks: 56 total, 1 running, 55 sleeping, 0 stopped, 0 zombie Cpu(s): 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 1019600k total, 316576k used, 703024k free, 7652k buffers Swap: 0k total, 0k used, 0k free, 258976k cached

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND           
   1 root      20   0 24188 2120 1300 S  0.0  0.2   0:00.56 init               
   2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd           
   3 root      20   0     0    0    0 S  0.0  0.0   0:00.07 ksoftirqd/0        
   6 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/0        
   7 root      RT   0     0    0    0 S  0.0  0.0   0:00.03 watchdog/0         
   8 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 cpuset             
   9 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 khelper            
  10 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kdevtmpfs          

The first several lines of output provide system statistics, such as CPU/memory load and the total number of running tasks.

You can see that there is 1 running process, and 55 processes that are considered to be sleeping because they are not actively using CPU cycles.

The remainder of the displayed output shows the running processes and their usage statistics. By default, top automatically sorts these by CPU usage, so you can see the busiest processes first. top will continue running in your shell until you stop it using the standard key combination of Ctrl+C to exit a running process. This sends a kill signal, instructing the process to stop gracefully if it is able to.

An improved version of top, called htop, is available in most package repositories. On Ubuntu 20.04, you can install it with apt:

   sudo apt install htop

After that, the htop command will be available:

   htop

Output

 Mem[|||||||||||           49/995MB]     Load average: 0.00 0.03 0.05 
 CPU[                          0.0%]     Tasks: 21, 3 thr; 1 running
 Swp[                         0/0MB]     Uptime: 00:58:11
 PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command
1259 root       20   0 25660  1880  1368 R  0.0  0.2  0:00.06 htop
   1 root       20   0 24188  2120  1300 S  0.0  0.2  0:00.56 /sbin/init
 311 root       20   0 17224   636   440 S  0.0  0.1  0:00.07 upstart-udev-brid
 314 root       20   0 21592  1280   760 S  0.0  0.1  0:00.06 /sbin/udevd --dae
 389 messagebu  20   0 23808   688   444 S  0.0  0.1  0:00.01 dbus-daemon --sys
 407 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.02 rsyslogd -c5
 408 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.00 rsyslogd -c5
 409 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.00 rsyslogd -c5
 406 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.04 rsyslogd -c5
 553 root       20   0 15180   400   204 S  0.0  0.0  0:00.01 upstart-socket-br

htop provides better visualization of multiple CPU threads, better awareness of color support in modern terminals, and more sorting options, among other features. Unlike top, It is not always installed by default, but can be considered a drop-in-replacement. You can exit htop by pressing Ctrl+C as with top. You can also learn more about how to use top and htop.

In the next section, you’ll learn about how to use tools to query specific processes. Step 2 – How To Use ps to List Processes

top and htop provide a dashboard interface to view running processes similar to a graphical task manager. A dashboard interface can provide an overview, but usually does not return directly actionable output. For this, Linux provides another standard command called ps to query running processes.

Running ps without any arguments provides very little information:

   ps

Output

 PID TTY          TIME CMD
1017 pts/0    00:00:00 bash
1262 pts/0    00:00:00 ps

This output shows all of the processes associated with the current user and terminal session. This makes sense if you are only running the bash shell and this ps command within this terminal currently.

To get a more complete picture of the processes on this system, you can run ps aux:

   ps aux

Output USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.2 24188 2120 ? Ss 14:28 0:00 /sbin/init root 2 0.0 0.0 0 0 ? S 14:28 0:00 [kthreadd] root 3 0.0 0.0 0 0 ? S 14:28 0:00 [ksoftirqd/0] root 6 0.0 0.0 0 0 ? S 14:28 0:00 [migration/0] root 7 0.0 0.0 0 0 ? S 14:28 0:00 [watchdog/0] root 8 0.0 0.0 0 0 ? S< 14:28 0:00 [cpuset] root 9 0.0 0.0 0 0 ? S< 14:28 0:00 [khelper] …

These options tell ps to show processes owned by all users (regardless of their terminal association) in a more human-readable format.

By making use of pipes, you can search within the output of ps aux using grep, in order to return the name of a specific process. This is useful if you believe it has crashed, or if you need to stop it for some reason.

   ps aux | grep bash

Output sammy 41664 0.7 0.0 34162880 2528 s000 S 1:35pm 0:00.04 -bash sammy 41748 0.0 0.0 34122844 828 s000 S+ 1:35pm 0:00.00 grep bash

This returns both the grep process you just ran, and the bash shell that’s currently running. It also return their total memory and CPU usage, how long they’ve been running, and in the highlighted output above, their process ID. In Linux and Unix-like systems, each process is assigned a process ID, or PID. This is how the operating system identifies and keeps track of processes.

A quick way of getting the PID of a process is with the pgrep command:

   pgrep bash

Output 1017

The first process spawned at boot, called init, is given the PID of “1”.

   pgrep init

Output 1

This process is then responsible for spawning every other process on the system. The later processes are given larger PID numbers.

A process’s parent is the process that was responsible for spawning it. Parent processes have a PPID, which you can see in the column headers in many process management applications, including top, htop and ps.

Any communication between the user and the operating system about processes involves translating between process names and PIDs at some point during the operation. This is why these utilities will always include the PID in their output. In the next section, you’ll learn how to use PIDs to send stop, resume, or other signals to running processes. Step 3 – How To Send Processes Signals in Linux

All processes in Linux respond to signals. Signals are an operating system-level way of telling programs to terminate or modify their behavior.

The most common way of passing signals to a program is with the kill command. As you might expect, the default functionality of this utility is to attempt to kill a process:

   kill PID_of_target_process

This sends the TERM signal to the process. The TERM signal tells the process to please terminate. This allows the program to perform clean-up operations and exit smoothly.

If the program is misbehaving and does not exit when given the TERM signal, you can escalate the signal by passing the KILL signal:

   kill -KILL PID_of_target_process

This is a special signal that is not sent to the program.

Instead, it is given to the operating system kernel, which shuts down the process. This is used to bypass programs that ignore the signals sent to them.

Each signal has an associated number that can be passed instead of the name. For instance, You can pass “-15” instead of “-TERM”, and “-9” instead of “-KILL”.

Signals are not only used to shut down programs. They can also be used to perform other actions.

For instance, many processes that are designed to run constantly in the background (sometimes called “daemons”) will automatically restart when they are given the HUP, or hang-up signal. The Apache webserver typically operates this way.

   sudo kill -HUP pid_of_apache

The above command will cause Apache to reload its configuration file and resume serving content.

Note: Many background processes like this are managed through system services which provide an additional surface for interacting with them, and it is usually preferable to restart the service itself rather than sending a HUP signal directly to one running process. If you review the configuration files of various services, you may find that the various service restart hooks are designed to do exactly that – send signals to specific processes – while also providing logs and other reporting.

You can list all of the signals that are possible to send with kill with the -l flag:

   kill -l

Output 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM

Although the conventional way of sending signals is through the use of PIDs, there are also methods of doing this with regular process names.

The pkill command works in almost exactly the same way as kill, but it operates on a process name instead:

   pkill -9 ping

The above command is the equivalent of:

   kill -9 `pgrep ping`

If you would like to send a signal to every instance of a certain process, you can use the killall command:

   killall firefox

The above command will send the TERM signal to every instance of firefox running on the computer. Step 4 – How To Adjust Process Priorities

Often, you will want to adjust which processes are given priority in a server environment.

Some processes might be considered mission critical for your situation, while others may be executed whenever there are leftover resources.

Linux controls priority through a value called niceness.

High priority tasks are considered less nice, because they don’t share resources as well. Low priority processes, on the other hand, are nice because they insist on only taking minimal resources.

When you ran top at the beginning of the article, there was a column marked “NI”. This is the nice value of the process:

   top

[secondary_label Output] Tasks: 56 total, 1 running, 55 sleeping, 0 stopped, 0 zombie Cpu(s): 0.0%us, 0.3%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 1019600k total, 324496k used, 695104k free, 8512k buffers Swap: 0k total, 0k used, 0k free, 264812k cached

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND           
1635 root      20   0 17300 1200  920 R  0.3  0.1   0:00.01 top                
   1 root      20   0 24188 2120 1300 S  0.0  0.2   0:00.56 init               
   2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd           
   3 root      20   0     0    0    0 S  0.0  0.0   0:00.11 ksoftirqd/0

Nice values can range between -19/-20 (highest priority) and 19/20 (lowest priority) depending on the system.

To run a program with a certain nice value, you can use the nice command:

   nice -n 15 command_to_execute

This only works when beginning a new program.

To alter the nice value of a program that is already executing, you use a tool called renice:

   renice 0 PID_to_prioritize

How To Use Bash's Job Control to Manage Foreground and Background Processes

Introduction

In this guide, we’ll talk about how bash, the Linux system, and your terminal come together to offer process and job control. In a previous guide, we discussed how the ps, kill, and nice commands can be used to control processes on your system.

This article will focus on managing foreground and background processes and will demonstrate how to leverage your shell’s job control functions to gain more flexibility in how you run commands. Managing Foreground Processes

Most processes that you start on a Linux machine will run in the foreground. The command will begin execution, blocking use of the shell for the duration of the process. The process may allow user interaction or may just run through a procedure and then exit. Any output will be displayed in the terminal window by default. We’ll discuss the basic way to manage foreground processes below. Starting a Process

By default, processes are started in the foreground. Until the program exits or changes state, you will not be able to interact with the shell.

Some foreground commands exit very quickly and return you to a shell prompt almost immediately. For instance, this command:

   echo "Hello World"

This would print “Hello World” to the terminal and then return you to your command prompt.

Other foreground commands take longer to execute, blocking shell access for the duration. This might be because the command is performing a more extensive operation or because it is configured to run until it is explicitly stopped or until it receives other user input.

A command that runs indefinitely is the top utility. After starting, it will continue to run and update its display until the user terminates the process:

   top

You can quit by typing “q”. Some processes don’t have a dedicated quit function. To stop those, you’ll have to use another method. Terminating a Process

Suppose we start a simple bash loop on the command line. We can start a loop that will print “Hello World” every ten seconds. This loop will continue forever, until explicitly terminated:

   while true; do echo "Hello World"; sleep 10; done

Loops have no “quit” key. We will have to stop the process by sending it a signal. In Linux, the kernel can send processes signals in order to request that they exit or change states. Linux terminals are usually configured to send the “SIGINT” signal (typically signal number 2) to current foreground process when the CTRL-C key combination is pressed. The SIGINT signal tells the program that the user has requested termination using the keyboard.

To stop the loop we’ve started, hold the control key and press the “c” key:

CTRL-C

The loop will exit, returning control to the shell.

The SIGINT signal sent by the CTRL-C combination is one of many signals that can be sent to programs. Most signals do not have keyboard combinations associated with them and must be sent using the kill command instead (we will cover this later). Suspending Processes

We mentioned above that foreground process will block access to the shell for the duration of their execution. What if we start a process in the foreground, but then realize that we need access to the terminal?

Another signal that we can send is the “SIGTSTP” signal (typically signal number 20). When we hit CTRL-Z, our terminal registers a “suspend” command, which then sends the SIGTSTP signal to the foreground process. This will basically pause the execution of the command and return control to the terminal.

To demonstrate, let’s use ping to connect to google.com every 5 seconds. We will precede the ping command with command, which will allow us to bypass any shell aliases that artificially set a maximum count on the command:

   command ping -i 5 google.com

Instead of terminating the command with CTRL-C, type CTRL-Z instead:

CTRL-Z

You will see output that looks like this:

Output

[1]+ Stopped ping -i 5 google.com

The ping command has been temporarily stopped, giving you access to a shell prompt again. We can use the ps process tool to show this:

   ps T

Output

 PID TTY      STAT   TIME COMMAND

26904 pts/3 Ss 0:00 /bin/bash 29633 pts/3 T 0:00 ping -i 5 google.com 29643 pts/3 R+ 0:00 ps t

We can see that the ping process is still listed, but that the “STAT” column has a “T” in it. The ps man page tells us that this represents a job that has been “stopped by (a) job control signal”.

We will discuss in more depth how to change process states, but for now, we can resume execution of the command in the foreground again by typing:

   fg

Once the process has resumed, terminate it with CTRL-C:

CTRL-C

Managing Background Processes

The main alternative to running a process in the foreground is to allow it to execute in the background. A background process is associated with the specific terminal that started it, but does not block access to the shell. Instead, it executes in the background, leaving the user able to interact with the system while the command runs.

Because of the way that a foreground processes interacts with its terminal, there can be only a single foreground process for every terminal window. Because background processes return control to the shell immediately without waiting for the process to complete, many background processes can run at the same time. Starting Processes

You can start a background process by appending an ampersand character (“&”) to the end of your commands. This tells the shell not to wait for the process to complete, but instead to begin execution and to immediately return the user to a prompt. The output of the command will still display in the terminal (unless redirected), but you can type additional commands as the background process continues.

For instance, we can start the same ping process from the last section in the background by typing:

   command ping -i 5 google.com &

You will see output from the bash job control system that looks like this:

Output

[1] 4287

You will also see the normal output from the ping command:

Output

PING google.com (74.125.226.71) 56(84) bytes of data. 64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=1 ttl=55 time=12.3 ms 64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=2 ttl=55 time=11.1 ms 64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=3 ttl=55 time=9.98 ms

However, you can also type commands at the same time. The background process’s output will be mixed among the input and output of your foreground processes, but it will not interfere with the execution of the foreground processes. Listing Background Processes

To see all stopped or backgrounded processes, you can use the jobs command:

   jobs

If you have the ping command running in the background, you will see something that looks like this:

Output

[1]+ Running command ping -i 5 google.com &

This shows that we currently have a single background process running. The [1] represents the command’s “job spec” or job number. We can reference this with other job and process control commands, like kill, fg, and bg by preceding the job number with a percentage sign. In this case, we’d reference this job as %1. Stopping Background Processes

We can stop the current background process in a few ways. The most straight forward way is to use the kill command with the associate job number. For instance, we can kill our running background process by typing:

   kill %1

Depending on how your terminal is configured, either immediately or the next time you hit ENTER, you will see the job termination status:

Output

[1]+ Terminated command ping -i 5 google.com

If we check the jobs command again, we’ll see no current jobs. Changing Process States

Now that we know how to start and stop processes in the background, we can talk about how to change their state.

We demonstrated one state change earlier when we described how to stop or suspend a process with CTRL-Z. When processes are in this stopped state, we can move a foreground process to the background or vice versa. Moving Foreground Processes to the Background

If we forget to end a command with & when we start it, we can still move the process to the background.

The first step is to stop the process with CTRL-Z again:

CTRL-Z

Once the process is stopped, we can use the bg command to start it again in the background:

   bg

You will see the job status line again, this time with the ampersand appended:

Output

[1]+ ping -i 5 google.com &

By default, the bg command operates on the most recently stopped process. If you’ve stopped multiple processes in a row without starting them again, you can reference the process by job number to background the correct process.

Note that not all commands can be backgrounded. Some processes will automatically terminate if they detect that they have been started with their standard input and output directly connected to an active terminal. Moving Background Processes to the Foreground

We can also move background processes to the foreground by typing fg:

   fg

This operates on your most recently backgrounded process (indicated by the “+” in the jobs output). It immediately suspends the process and puts it into the foreground. To specify a different job, use its job number:

   fg %2

Once a job is in the foreground, you can kill it with CTRL-C, let it complete, or suspend and background it again. Dealing with SIGHUPs

Whether a process is in the background or in the foreground, it is rather tightly tied with the terminal instance that started it. When a terminal closes, it typically sends a SIGHUP signal to all of the processes (foreground, background, or stopped) that are tied to the terminal. This signals for the processes to terminate because their controlling terminal will shortly be unavailable. What if you want to close a terminal but keep the background processes running?

There are a number of ways of accomplishing this. The most flexible ways are typically to use a terminal multiplexer like screen or tmux, or use a utility that provides at least the detach functionality of those, like dtach.

However, this isn’t always an option. Sometimes these programs aren’t available or you’ve already started the process you need to continue running. Sometimes these are overkill for what you need to accomplish. Using nohup

If you know when starting the process that you will want to close the terminal before the process completes, you can start it using the nohup command. This makes the started process immune to the SIGHUP signal. It will continue running when the terminal closes. It will be reassigned as a child of the init system:

   nohup ping -i 5 google.com &

You will see a line that looks like this, indicating that the output of the command will be written to a file called nohup.out (in the current directory if writeable, otherwise to your home directory):

Output

nohup: ignoring input and appending output to ‘nohup.out’

This is to ensure that output is not lost if the terminal window is closed.

If you close the terminal window and open another one, the process will still be running. You will not see it in the output of the jobs command because each terminal instance maintains its own independent job queue. The terminal closing caused the ping job to be destroyed even though the ping process is still running.

To kill the ping process, you’ll have to look up its process ID (or “PID”). You can do that with the pgrep command (there is also a pkill command, but this two-part method ensures that we are only killing the intended process). Use pgrep and the -a flag to search for the executable:

   pgrep -a ping

Output

7360 ping -i 5 google.com

You can then kill the process by referencing the returned PID, which is the number in the first column:

   kill 7360

You may wish to remove the nohup.out file if you don’t need it anymore. Using disown

The nohup command is helpful, but only if you know you will need it at the time you start the process. The bash job control system provides other methods of achieving similar results with the disown built in command.

The disown command, in its default configuration, removes a job from the jobs queue of a terminal. This means that it can no longer be managed using the job control mechanisms discussed in this guide (like fg, bg, CTRL-Z, CTRL-C). It will immediately be removed from the list in the jobs output and no longer associated with the terminal.

The command is called by specifying a job number. For instance, to immediately disown job 2, we could type:

   disown %2

This leaves the process in a state not unlike that of a nohup process after the controlling terminal has been closed. The exception is that any output will be lost when the controlling terminal closes if it is not being redirected to a file.

Usually, you don’t want to remove the process completely from job control if you aren’t immediately closing your terminal window. You can pass the -h flag to the disown process instead in order to mark the process to ignore SIGHUP signals, but to otherwise continue on as a regular job:

   disown -h %1

In this state, you could use normal job control mechanisms to continue controlling the process until closing the terminal. Upon closing the terminal, you will, once again, be stuck with a process with nowhere to output if you didn’t redirect to a file when starting it.

To work around that, you can try to redirect the output of your process after it is already running. This is outside the scope of this guide, but you can take a look at this post to get an idea of how you would do that. Using the huponexit Shell Option

Bash also has another way of avoiding the SIGHUP problem for child processes. The huponexit shell option controls whether bash will send its child processes the SIGHUP signal when it exits. Note

The huponexit option only affect the SIGHUP behavior when a shell session termination is initiated from within the shell itself. Some examples of when this applies is when the exit command or CTRL-D is hit within the session.

When a shell session is ended through the terminal program itself (through closing the window, etc.), the command huponexit will have no affect. Instead of bash deciding on whether to send the SIGHUP signal, the terminal itself will send the SIGHUP signal to bash, which will then (correctly) propagate the signal to its child processes.

Despite the above caveats, the huponexit option is perhaps one of the easiest. You can see whether this feature is on or off by typing:

   shopt huponexit

To turn it on, type:

   shopt -s huponexit

Now, if you exit your session by typing exit, your processes will all continue to run:

   exit

This has the same caveats about program output as the last option, so make sure you have redirected your processes’ output if it is important prior to closing your terminal.

Эх сурвалж: