grepSearch text for lines that match a pattern
grep prints the lines of a file (or of a pipe) that match a pattern. It is the first tool you reach for in an incident: find the errors, see the lines around a crash, count failures, or find where a setting is defined across a whole code base.
grep [OPTION]... PATTERN [FILE]...An alert says the orders API is unhealthy. You want every ERROR line, how many there are, and where the FATAL is.
grepGlobal Regular Expression Print: prints every line that matches.
grep compiles the pattern once into a fast matcher: a Boyer-Moore style scan for fixed strings, a DFA for most regexes, and a slower backtracking engine only for back-references or -P. It then read()s the file in large chunks (tens of kilobytes) and searches the whole buffer at once; only when something matches does it look backwards and forwards for the newline characters that bound the line. That is why grep is far faster than reading line by line. If a chunk contains NUL bytes it treats the file as binary and prints 'binary file matches' instead of the line. The exit status is 0 if any line matched, 1 if none did and 2 on an error such as a missing file, which is what makes grep -q useful in if statements. When stdout is a pipe instead of a terminal, grep block-buffers its output, so tail -f | grep | other-command can look stuck until --line-buffered is added.
-iIgnore case-vInvert: print lines that do NOT match-nShow line numbers-cPrint only the number of matching lines (per file)-l / -LPrint only names of files that match / that don't match-r / -RSearch directories recursively (-R also follows symlinks)-wMatch whole words only (error, not errors or error_count)-EExtended regex: a|b, (x)+, [0-9]{3} without backslashes-FFixed string, no regex: dots and brackets are literal (fast for IPs)-oPrint only the matched part, one per line (great before sort | uniq -c)-A N / -B N / -C NShow N lines After / Before / around each match-m NStop after N matching lines-qQuiet: print nothing, just set the exit status (for scripts)--include / --exclude-dirWith -r, limit files by glob or skip directories like .git or node_modulesgrep 10.0.2.1 access.log to find one IPThe dot is a regex wildcard, so it also matches 10.0.231 or 10.0.2.11, 10.0.2.12 ... and you get the wrong lines.
grep -Fw '10.0.2.1' access.log # -F literal, -w whole wordtail -f app.log | grep ERROR | tee errors.txt (and nothing appears)When grep writes into a pipe it block-buffers (a few KB) before flushing, so matches arrive late or seem never to come.
tail -f app.log | grep --line-buffered ERROR | tee errors.txtps aux | grep nginx (the grep shows up in its own results)The grep process's own command line contains 'nginx', so it matches itself and scripts count one process too many.
pgrep -a nginx # or: ps aux | grep '[n]ginx'grep -r password /Recursing from / walks /proc, /sys and every mount: it takes ages, prints thousands of permission errors and may hang on device files.
grep -rn --exclude-dir={.git,node_modules} password /etc/myapp ~/appgrep ERROR app.log.*.gz to search rotated logsThe files are compressed: grep searches the gzip bytes and silently finds nothing (or prints 'binary file matches').
zgrep ERROR app.log.*.gzTry these on a Linux machine of your own. Each task has a hint and a solution.
Count how many lines in ~/logs/app.log contain ERROR (in any case).
Show every line in ~/logs/app.log that is NOT INFO or DEBUG, with line numbers.
Print the 3 lines before and after the first FATAL or CRITICAL line in any log under /var/log/app.
List only the names of files under ~/app that mention 'password' (any case), skipping .git.
Write a one-liner that prints 'DOWN' if /var/log/app has no line containing 'healthy'.
grepSearch text for lines that match a pattern
grep prints the lines of a file (or of a pipe) that match a pattern. It is the first tool you reach for in an incident: find the errors, see the lines around a crash, count failures, or find where a setting is defined across a whole code base.
grep [OPTION]... PATTERN [FILE]...An alert says the orders API is unhealthy. You want every ERROR line, how many there are, and where the FATAL is.
grepGlobal Regular Expression Print: prints every line that matches.
grep compiles the pattern once into a fast matcher: a Boyer-Moore style scan for fixed strings, a DFA for most regexes, and a slower backtracking engine only for back-references or -P. It then read()s the file in large chunks (tens of kilobytes) and searches the whole buffer at once; only when something matches does it look backwards and forwards for the newline characters that bound the line. That is why grep is far faster than reading line by line. If a chunk contains NUL bytes it treats the file as binary and prints 'binary file matches' instead of the line. The exit status is 0 if any line matched, 1 if none did and 2 on an error such as a missing file, which is what makes grep -q useful in if statements. When stdout is a pipe instead of a terminal, grep block-buffers its output, so tail -f | grep | other-command can look stuck until --line-buffered is added.
-iIgnore case-vInvert: print lines that do NOT match-nShow line numbers-cPrint only the number of matching lines (per file)-l / -LPrint only names of files that match / that don't match-r / -RSearch directories recursively (-R also follows symlinks)-wMatch whole words only (error, not errors or error_count)-EExtended regex: a|b, (x)+, [0-9]{3} without backslashes-FFixed string, no regex: dots and brackets are literal (fast for IPs)-oPrint only the matched part, one per line (great before sort | uniq -c)-A N / -B N / -C NShow N lines After / Before / around each match-m NStop after N matching lines-qQuiet: print nothing, just set the exit status (for scripts)--include / --exclude-dirWith -r, limit files by glob or skip directories like .git or node_modulesgrep 10.0.2.1 access.log to find one IPThe dot is a regex wildcard, so it also matches 10.0.231 or 10.0.2.11, 10.0.2.12 ... and you get the wrong lines.
grep -Fw '10.0.2.1' access.log # -F literal, -w whole wordtail -f app.log | grep ERROR | tee errors.txt (and nothing appears)When grep writes into a pipe it block-buffers (a few KB) before flushing, so matches arrive late or seem never to come.
tail -f app.log | grep --line-buffered ERROR | tee errors.txtps aux | grep nginx (the grep shows up in its own results)The grep process's own command line contains 'nginx', so it matches itself and scripts count one process too many.
pgrep -a nginx # or: ps aux | grep '[n]ginx'grep -r password /Recursing from / walks /proc, /sys and every mount: it takes ages, prints thousands of permission errors and may hang on device files.
grep -rn --exclude-dir={.git,node_modules} password /etc/myapp ~/appgrep ERROR app.log.*.gz to search rotated logsThe files are compressed: grep searches the gzip bytes and silently finds nothing (or prints 'binary file matches').
zgrep ERROR app.log.*.gzTry these on a Linux machine of your own. Each task has a hint and a solution.
Count how many lines in ~/logs/app.log contain ERROR (in any case).
Show every line in ~/logs/app.log that is NOT INFO or DEBUG, with line numbers.
Print the 3 lines before and after the first FATAL or CRITICAL line in any log under /var/log/app.
List only the names of files under ~/app that mention 'password' (any case), skipping .git.
Write a one-liner that prints 'DOWN' if /var/log/app has no line containing 'healthy'.