惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

I
InfoQ
G
Google Developers Blog
Engineering at Meta
Engineering at Meta
月光博客
月光博客
博客园 - 聂微东
博客园 - Franky
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
有赞技术团队
有赞技术团队
A
About on SuperTechFans
Microsoft Azure Blog
Microsoft Azure Blog
Blog — PlanetScale
Blog — PlanetScale
U
Unit 42
T
Tailwind CSS Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
云风的 BLOG
云风的 BLOG
S
SegmentFault 最新的问题
F
Fortinet All Blogs
H
Help Net Security
J
Java Code Geeks
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 叶小钗
L
LangChain Blog
Martin Fowler
Martin Fowler
N
Netflix TechBlog - Medium

lvbibir's Blog

shell | 磁盘空间分析脚本 Linux cat 和 tee 命令写入文件 python | 使用 uv 管理你的 python 环境 Claude Code 完整配置指南 windows | mihomo 内核独立部署指南 linux | 磁盘扩容 wsl | 释放长久运行占用的磁盘空间 mysql | 线程上限问题处理 麒麟 7.6 安装谷歌 OTP 认证模块 suse 12sp5 升级 openssh 及 openssl suse 12sp5 部署 mysql 5.7 《谁的青春不迷茫》 docker | centos7 部署 docker vim | 基础配置和使用 windows | rime 输入法 & 雾凇方案 shell | sshpass 批量传输文件及执行命令 wsl | 原生 linux 方式安装 docker nodejs | fnm + pnpm 开发环境配置 wsl | 安装配置 miniconda 虚拟环境 wsl | 自动更新系统代理 wsl | bashrc 环境变量不正确加载的处理方法 wsl | win10 安装 wsl2 troubleshooting | ssh 成功但是 scp 失败 linux | 常用命令总结 docker 部署 piclist shell | 检测网站存活并自动钉钉告警 Zabbix | 监控端口连通性并自动追踪 TCP 路由 windows | 自定义开机快速启动项 windows | miniconda 配置 python 虚拟环境 Zabbix | 监控主机到指定 ip 的流量大小
shell | 不同执行方式的区别
lvbibir · 2022-06-01 · via lvbibir's Blog

0 前言

本文参考以下链接:

1 不同的执行方式

shell 脚本通常有 sh filenamebash filename./filenamesource filename 这四种执行方式

  • source filename 可以使用 . filename 代替,在当前的 bash 环境下读取并执行脚本文件中的命令,且脚本文件的变量,在脚本执行完成后会保存下来
  • ./filenamesh filename 或者 bash filename 是等效的,都是开启一个子 shell 来运行脚本文件,脚本中设置的变量执行完毕后不会保存

./filename 外,source filename. filenamesh filenamebash filename 都是不需要执行权限的

变量和权限问题示例

# 设置临时变量,仅在当前 bash 环境生效
[root@lvbibir ~]# name=lvbibir
[root@lvbibir ~]# echo $name
lvbibir
[root@lvbibir ~]#
[root@lvbibir ~]# cat test.sh
#!/bin/bash
echo $name

# source 或者 . 可以获取到父 bash 环境的变量
[root@lvbibir ~]# source test.sh
lvbibir
[root@lvbibir ~]# . test.sh
lvbibir

# sh、bash、./三种方式都使用了子 bash 环境,所以无法获取父 bash 环境的变量
# ./ 方式需要脚本有执行权限
[root@lvbibir ~]# sh test.sh

[root@lvbibir ~]# bash test.sh

[root@lvbibir ~]# ./test.sh
-bash: ./test.sh: Permission denied
[root@lvbibir ~]# chmod a+x test.sh
[root@lvbibir ~]# ./test.sh

同理,使用 source 或者 . 也可以在 bash 环境中获取到脚本中设置的变量

[root@lvbibir ~]# cat > test.sh << EOF
> #!/bin/bash
> number=22
>
> EOF
[root@lvbibir ~]# echo $number

# sh bash ./ 三种方式无法获取脚本中的变量
[root@lvbibir ~]#
[root@lvbibir ~]# sh test.sh
[root@lvbibir ~]# echo $number

[root@lvbibir ~]# bash test.sh
[root@lvbibir ~]# echo $number

[root@lvbibir ~]# ./test.sh
[root@lvbibir ~]# echo $number

# source 方式可以获取脚本中的变量
[root@lvbibir ~]# source test.sh
[root@lvbibir ~]# echo $number
22
[root@lvbibir ~]#

2 其他问题

关于是否在子 bash 环境运行的区别出了变量问题还会存在一些其他影响,如下测试

已知目前存在一个 mysqld 进程,其 pid 为 29426 ,写一个监控 pid 的脚本

[root@lvbibir ~]# cat test.sh
#!/bin/bash
process=$1
pid=$(ps -elf | grep $process | grep -v grep | awk '{print $4}')
echo $pid

两种方式分别运行一下

[root@lvbibir ~]# sh test.sh mysqld
27038 27039 29426
[root@lvbibir ~]# bash test.sh mysqld
27047 27048 29426
[root@lvbibir ~]# ./test.sh mysqld
27056 27057 29426
[root@lvbibir ~]#
[root@lvbibir ~]# source test.sh mysqld
29426
[root@lvbibir ~]# . test.sh mysqld
29426
[root@lvbibir ~]#

问题出现了,由于某种原因导致子 bash 环境中执行的脚本监控到多个 pid ,给脚本添加个 sleep 来看下

[root@lvbibir ~]# cat test.sh
#!/bin/bash
process=$1
pid=$(ps -elf | grep $process | grep -v grep | awk '{print $4}')
echo $pid
sleep 30

[root@lvbibir ~]# ./test.sh mysqld
27396 27397 29426

新开一个终端,查看进程

image-20220630160731914

  • 第一个 pid 是在子 shell 中执行监控脚本的进程号
  • 第二个 pid 不太清楚哪里来的,也 grep 不到这个进程号,应该是脚本执行一瞬间就释放掉了
  • 第三个 pid 是 mysql 实际运行中的进程号

实际中脚本的 pid 和 mysqld 的 pid 顺序不太一样,取决于 pid 的大小

在脚本再添加个 grep 过滤掉脚本本身的进程来规避这个问题

[root@lvbibir ~]# cat test.sh
#!/bin/bash
process=$1
pid=$(ps -elf | grep $process | grep -v grep | grep -v bash | awk '{print $4}')
echo $pid

[root@lvbibir ~]# ./test.sh mysqld
29426

以上

wechat_pay

微信

alipay

支付宝