shell
<h2>原理</h2>
<p>shell 脚本中调用命令时:</p>
<ul>
<li>
<p>如果是直接调用,则是直接起子进程</p>
</li>
<li>如果要获取命令的输出结果,则是起 pipe 和子进程,通过 pipe 获取子进程的输出</li>
</ul>
<h2>注意</h2>
<p>文件锁注意在起子进程时会继续被占用</p>
<h2>$ 用法</h2>
<pre><code class="language-sh">$# # 参数个数,不包括 $0
$@ # 获取所有参数列表,不包括 $0。
# 不加括号时,单纯按照空格来分割元素;
# 加括号时则是按照实际的参数来处理。所以脚本马甲要用 &quot;$@&quot; 传递参数,注意有引号。(不加引号有什么影响?答:当参数中有 &quot;aaa bbb&quot; 这种就会有问题)
$* # 不加引号时,和 $@ 一样,效果都是数组;
# 加引号时,&quot;$*&quot; 把所有参数合并成一个字符串;而 &quot;$@&quot; 是字符串数组。
$$ # 当前进程 ID
$! # 后台运行的最后一个进程的 ID 号
$PPID # 父进程</code></pre>
<p>测试如下(传入参数只有 4 个,如果不加引号,会被当成 5 个参数):</p>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=9d1460792829e5044c0cb35090340ae1&amp;file=file.png" alt="" /></p>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=eeb9ca3da08ce4693486c655d3c0219f&amp;file=file.png" alt="" /></p>
<p>注意:如果传入的参数多于 9 个,则不能使用 $10 来引用第 10 个参数,而是要用 ${10} 来引用。</p>
<h2>基础</h2>
<p>1、rm -f 不会判断文件是否存在,因为不存在也不会报错</p>
<p>2、临时文件直接 mv -f 到正式文件,避免磁盘不足等问题</p>
<p>3、开头为 #!/bin/bash</p>
<p>4、命令中的变量加引号,防止注意,如 <code>ls &quot;$foo&quot;</code>。需要注意:这种情况下,如果路径中含有 * 号,则不生效</p>
<h2>脚本做马甲</h2>
<p>脚本马甲要用 "$@" 传递参数,注意有引号</p>
<h2>for</h2>
<pre><code class="language-shell">#!/bin/bash
max_count=5
for ((i=max_count; i&gt;0; i--)); do
echo $i
done</code></pre>
<h2>split string</h2>
<pre><code class="language-shell">#!/usr/bin/env bash
IN=&quot;bla@some.com;john@home.com&quot;
mails=$(echo $IN | tr &quot;;&quot; &quot;\n&quot;)
for addr in $mails
do
echo &quot;&gt; [$addr]&quot;
done</code></pre>
<h2>awk 命令</h2>
<p>使用示例:</p>
<pre><code class="language-shell"># 匹配 /bin/sh 和 /bin/bash 行
PSLIST=`ps aux --cols=1000 | awk '/\/bin\/(ba)?sh/{print $11&quot; &quot;$12&quot; &quot;$13}'`</code></pre>
<ul>
<li>
<p>getline 带参数和不带参数,效果是不一样的:</p>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=535c984bb1d2ba6813e4143379b6f141" alt="" /></p>
<p>总结:getline 是获取下一行内容。当带变量时,不改变内部环境变量;不带变量就会改变变量</p>
</li>
<li>
<p>变量截取:</p>
<p><a href="https://www.runoob.com/linux/linux-shell-variable.html">https://www.runoob.com/linux/linux-shell-variable.html</a></p>
</li>
<li>
<p>参考文档</p>
<p><a href="https://www.bookstack.cn/read/junmajinlong-awk/0e1306c3b34de2ec.md">https://www.bookstack.cn/read/junmajinlong-awk/0e1306c3b34de2ec.md</a></p>
</li>
</ul>
<h2>shell 判断</h2>
<p>-z 判断变量时:</p>
<ul>
<li>
<p>如果关注空内容(即都是空格),则变量要带引号</p>
</li>
<li>如果不关注内容,则变量不要加引号</li>
</ul>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=e52e905e9ba97bfa353829f91773e0ec&amp;file=file.png" alt="" /></p>
<p>-n 判断变量时(建议用 ! -z 替换):</p>
<ul>
<li>变量必须加引号,否则会有问题。但空内容(即都是空格)会被认为“有内容”</li>
</ul>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=58d9c31087c8b8b5852488ab0314a31f&amp;file=file.png" alt="" /></p>
<h2>获取脚本自身的目录</h2>
<p>获取执行脚本全路径:</p>
<p><code>readlink -e $0</code></p>
<p>获取目录:</p>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=81f27fb2e5ed3bac93d4e36759cbfc74&amp;file=file.png" alt="" /></p>
<p>> 参考资料:<a href="https://blog.csdn.net/10km/article/details/51906821">https://blog.csdn.net/10km/article/details/51906821</a></p>
<h2>调用命令</h2>
<pre><code class="language-shell"># 如果是这样调用命令,则是通过管道 pipe([3, 4]) 来获取输出,获取完成后就会关掉句柄。而且是每次这样调用,都重新创建
a=`ls /tmp`
# 如果是直接调用命令,则是直接直接输出,没用管道
ls /tmp</code></pre>
<h2>shell 中关闭句柄</h2>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=cf25ed156c0dab09accbc5b0dbfab2e9&amp;file=file.png" alt="" /></p>
<p>> 参考文档:<a href="https://blog.csdn.net/vanloswang/article/details/40862081">https://blog.csdn.net/vanloswang/article/details/40862081</a></p>
<h2>获取某个分区占用情况</h2>
<pre><code class="language-shell">df -hm /var</code></pre>
<h2>去掉 %</h2>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=60d990d22e63a68dd34888c52bb4b173&amp;file=file.png" alt="" /></p>
<h2>变量截取</h2>
<p>> <a href="https://blog.csdn.net/jined/article/details/124196546">https://blog.csdn.net/jined/article/details/124196546</a></p>
<h2>kill</h2>
<pre><code class="language-sh">kill -15 0 # 进程号为 0 则将信号发给当前进程组,包括自已。(当脚本有后台运行的任务时,可以用此方法杀掉。shell 脚本的子进程属于同一个进程组;但 ssh 窗口起的子进程,却不是同一个进程组)
kill -15 -1 # 进程号为 -1,则杀掉所有能杀掉的进程
kill -15 -n # 进程号小于 -1,则将信息发给进程组 n
kill -0 {id} # 不发信号,只是检查 进程号或进程组号 是否存在/权限。备注:比较 ps 高效;但测试似乎不能测试进程组号</code></pre>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=ae009a20009fb474909d38a0a7276193&amp;file=file.png" alt="" /></p>