Linux Bash 使用介绍
介绍
各种文件说明
/etc/profile
系统环境参数,对系统的所有用户生效/etc/bashrc
bash 参数设置,只要用户使用 bash 就生效~/.bash_profile
功能同 /etc/profile
,仅对当前用户生效~/.bashrc
功能同 /etc/bashrc
,仅对当前用户生效- 非交互式的,当以用户身份运行命令时就读取该文件
- docker exec 时是非交互方式进入 bash,该文件生效
bash 命令的 --rcfile
参数,指定另一个脚本代替 .bashrc
man bash
中记录了4中交互模式
login
+ interactive(交互式)
- 直接登陆到机器获得的第一个 shell
- 使用
ssh user@remote
获得的 shell
login
+ non-interactive
non-login
+ interactive
non-login
+ non-interactive
bash script.sh
ssh user@remote command
+----------------+--------+-----------+---------------+
| | login |interactive|non-interactive|
| | |non-login |non-login |
+----------------+--------+-----------+---------------+
|/etc/profile | A | | |
+----------------+--------+-----------+---------------+
|/etc/bash.bashrc| | A | |
+----------------+--------+-----------+---------------+
|~/.bashrc | | B | |
+----------------+--------+-----------+---------------+
|~/.bash_profile | B1 | | |
+----------------+--------+-----------+---------------+
|~/.bash_login | B2 | | |
+----------------+--------+-----------+---------------+
|~/.profile | B3 | | |
+----------------+--------+-----------+---------------+
|BASH_ENV | | | A |
+----------------+--------+-----------+---------------+
说明
- 若不生效,检查
~/.bashrc
中的 PS1
是否有空监测 - 一些场景
- 登陆机器后的第一个shell:
login + interactive
- 新启动一个shell进程,如运行bash:
non-login + interactive
- 执行脚本,如bash script.sh:
non-login + non-interactive
- 运行头部有如
#!/usr/bin/env bash
的可执行文件,如./executable:non-login + non-interactive
- 通过ssh登陆到远程主机:
login + interactive
- 远程执行脚本,如
ssh user@remote script.sh
:non-login + non-interactive
- 远程执行脚本,同时请求控制台,如
ssh user@remote -t 'echo $PWD'
:non-login + interactive
- 在图形化界面中打开terminal:
- Linux上:
non-login + interactive
- Mac OS X上:
login + interactive
特殊变量
shell 文件的特殊变量:
$0
当前脚本的文件名$n(n≥1)
传递给脚本或函数的参数。n 是一个数字,表示第几个参数$#
传递给脚本或函数的参数个数$*
/ $@
传递给脚本或函数的所有参数$?
上个命令的退出状态,或函数的返回值$$
当前 Shell 进程 PID。对于 Shell 脚本,就是这些脚本所在的进程 ID
示例
多线程示例
#!/bin/bash
function my_cmd(){
local ppid=$$
local pid=$BASHPID
local gpu_id=$1
export CUDA_VISIBLE_DEVICES=${gpu_id}
echo "ppid: ${ppid}, pid: ${pid}, gpu_id: ${gpu_id}, begin sleep 10 s"
sleep 10
echo "ppid: ${ppid}, pid: ${pid}, gpu_id: ${gpu_id} sleep 10 s done."
# 当进程结束以后,再向fd6中加上一个回车符,即补上了read -u6减去的那个
echo ${gpu_id} >&6
}
tmp_fifofile="/tmp/$$.fifo"
# 新建一个fifo类型的文件
mkfifo $tmp_fifofile
# 将fd6指向fifo类型
exec 6<>$tmp_fifofile
# rm $tmp_fifofile
# 最大可同时执行线程数量
thread_num=5
# 任务总数
job_num=100
# 根据线程总数量设置令牌个数
for ((i=0;i<${thread_num};i++));do
echo ${i}
done >&6
for ((i=0;i<${job_num};i++));do # 任务数量
# 一个read -u6命令执行一次,就从fd6中减去一个回车符,然后向下执行,
# fd6中没有回车符的时候,就停在这了,从而实现了线程数量控制
read -u6 gpu_id
#可以把具体的需要执行的命令封装成一个函数
{
my_cmd ${gpu_id}
} &
done
wait
# 关闭fd6
exec 6>&-
echo "over"