Why does the AnQiCMS `stop.sh` script use `awk '{printf $2}'` after `grep` to get the PID?
In the operation and maintenance of Anqi CMS, we often encounter situations where we need to start or stop services.For the AnQiCMS project developed based on the Go language, it usually runs as a single binary executable file.To achieve smooth service management,stop.shThe script plays a core role. Instop.shIn the script, getting the PID (Process ID) of the running AnQiCMS process is a key step, andgrepimmediately followsawk '{printf $2}'The combination is meticulously designed for this purpose.
The starting point for obtaining process information:ps -ef
To understand this combination, we first need to start fromps -efthe command.ps(process status) is a command used in Linux/Unix systems to report the current status of processes. When combined-efWhen an option is selected, it will display complete information about all running processes, including the user, PID, parent PID, CPU usage, start time, and the complete command path.
ps -efThe command output is usually like this:
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Jan01 ? 00:00:10 /sbin/init
user 12345 1 0 10:00 ? 00:00:05 /path/to/anqicms
user 12346 12345 0 10:00 ? 00:00:01 /path/to/anqicms --child-process
user 20000 19999 0 11:30 pts/0 00:00:00 grep --color=auto anqicms
In which, the second column (PID) is the process ID we are looking for.
Precise filtering:grep '\<anqicms\>' | grep -v grep
Just useps -efIt will list all processes, and we need to filter out the processes related to AnQiCMS. At this point,grepthe command comes into play.
grep '\<anqicms\>':grepUsed to search for a specified pattern in text. Here, it is used to find lines containing the 'anqicms' string.\<and\>It is a word boundary marker in regular expressions. This meansgrepIt will precisely match “anqicms” as a whole word, not as a substring of “myanqicms” or “anqicms_test”.This ensures that we only match the main program of AnQiCMS and not other unrelated processes that may contain "anqicms".- This step will output to only include
anqicmsthe lines of the process.
grep -v grep:grep -vThe function is to reverse match, that is, to exclude lines containing specified patterns.- When we use pipes.
ps -ef | grep anqicmsthen,grep anqicmsThis command itself will become a running process, its command string naturally contains "anqicms". If not distinguished,grepThe PID of the command itself is also returned, which is not what we want. grep -v grepThe purpose is to exclude.grepCommand the process information of itself, ensure that the PID we get belongs only to the AnQiCMS service.
After these twogrepThe filtering, the output we get will be clean, only containing the complete lines of the AnQiCMS service process (if it is running).
Extract the core:awk '{printf $2}'
Now we have obtained the line that only contains AnQiCMS process information, the next step is to accurately extract the PID from these lines.awk(Aho, Weinberger, and Kernighan) is a powerful text processing tool, it is very suitable for this column-based data extraction.
awk '{...}':awkThe default field separator is a space or tab, and each line is parsed into multiple fields, using$1,$2,$3to represent.$2Inps -efIn the output, the process ID (PID) is located in the second column. Therefore,$2Exactly represents the needed PID.printf $2:printfIsawkA function within, similar to the C language.printfUsed for formatting output.- with
print $2different,printf $2After printing.$2The value after.The line break is not automatically added. - In a shell script, when we want to assign the output of a command to a variable, we usually expect the output to be a single-line string without any additional newline characters. If we use
print $2,existsVariables may capture a newline character following the PID, which may cause issues in subsequent commands (thoughkillthe command may cause problems (althoughkillIt usually handles trailing newline characters). Moreover, if there are multiple AnQiCMS processes (although it is typically a single main process for Go applications),printf $2Will concatenate all found PIDsJoinInto a long string (for example,1234567890), which is executedkill -9 $existsthen,killThe command attempts to kill a non-existent PID instead of all matching PIDs. However, for AnQiCMS which usually runs a single main Go process in the scenario,printf $2The expected behavior is to return a unique PID and assign it as a single string toexistsa variable, forkillcommand usage. When no matching process is found,awkno content will be output,existsThe variable will be empty, thereby inif [ $exists -eq 0 ]the context, it is interpreted as 0 by the Shell.
The advantage of this combination
- Accuracy: Pass
grepand word boundary matching andgrep -vThe self-exclusion ensures that only the target AnQiCMS process is focused. - Robustness:
awkDuring processingpsWhen outputting, it is simpler thancutThe command is more flexible becausepsThe column width and delimiter may vary slightly due to the system or parameters, butawkthe field recognition ability is usually more stable. - Simple and efficientThis pipeline command chain implements the target of locating and extracting the specific PID from a large amount of process information in a concise manner, suitable for script automation tasks.
- Variable friendly:
awkCombineprintfAvoided extra line breaks, making the output result directly usable for shell variable assignment, convenient for subsequent operationskillOperation.
In summary, AnQiCMSstop.shin the scriptgrepafter usingawk '{printf $2}'The combination is to locate the PID of the AnQiCMS main process in a complex process list in an accurate, robust, and efficient manner, and extract it into a clean string so that it can be passed throughkillCommand to terminate.
Frequently Asked Questions (FAQ)
1. Why not use directly?pkill anqicmsTo stop the process?
pkillThe command indeed provides a more concise way to terminate processes by name. However, its behavior and default matching patterns may vary slightly across different systems. For example, ifpkillBy default, substring matching is performed, so any process containing 'anqicms' (such as a test script or log file processor) may be mistakenly killed.ps -ef | grep ... | awk ...This chained command provides a finer, more transparent control flow, allowing the operator to precisely define matching rules (such as\<anqicms\>Ensure word boundary matching to reduce the risk of false positives. In production environments that require high stability and controllability, this explicit layered filtering method is sometimes morepkillpreferred.
2. If multiple instances of namedanqicmsthe process,stop.shHow will it be handled?
Instop.shexisting implementations of the scriptawk '{printf $2}'will match all process PIDsJoinForm a long string without spaces or separators. For example, if the PID is12345and67890,existsthe variable will become"1234567890". When the script executeskill -9 $existsthen,killthe command will attempt to terminate1234567890This PID, and this number composed of multiple PIDs usually does not correspond to any actual running process. This means the script will not be able to terminate all matching processes correctly.anqicmsProcess. For applications like AnQiCMS, it is usually expected to run only one main process. If multiple processes existanqicmsProcess, this usually indicates an abnormal situation or deployment error. A more robust approach is to use a loop (for examplefor pid in $(ps -ef | grep ... | awk '{print $2}'); do kill -9 $pid; done) to terminate each matching PID one by one.
3.awkIs the method for extracting PID more recommended than other tools (such ascut)?
Yes, when extracting specific columns fromps -efsuch command output,awkit is usually better thancutMore recommended.cutPrimarily based on fixed positions or a single delimiter for trimming, whilepsThe output format may sometimes have a variable number of spaces as separators, causing the column positions to be fixed.awkBy default, any number of whitespace characters are used as field separators, making it more flexible and robust during processingpsand more resistant to failure due to minor format changes. Therefore,awk '{printf $2}'It is a common and reliable choice.