一、System
system()函数是C++标准库中的一个函数,它允许程序执行系统命令。该函数定义在头文件中。 返回 0 表示命令执行成功,-1 表示系统错误 该函数谨慎使用,不要让用户的输入传递给该函数 system() 会创建新的进 程来执行命令,比较占用资源 对于跨平台代码,需要注意兼容性,可以使用预编译写 几套
# ifdef _WIN32
system ( "mkdir new_folder" ) ;
# else
system ( "mkdir -p new_folder" ) ;
# endif
system ( "ls" ) ;
system ( "clear" ) ;
int result = system ( "somecommand" ) ;
if ( result == 0 ) {
std:: cout << "命令执行成功" << std:: endl;
} else {
std:: cout << "命令执行失败" << std:: endl;
}
二、exec族函数
exec族函数是一组用于执行新程序的函数,它们会用新的进程映像替换当前进程的映像 相当于是替换了该进程,借壳(pid)上市 经常和fork函数一同使用
1.替换原理
当前进程的内存被清空:调用exec时,当前进程的地址空间(包括代码、数据和堆栈)将被完全清除。 加载新程序:新程序(指定的可执行文件)会被加载到进程的内存中,覆盖原来的进程内容。 新的程序开始执行:加载完新程序后,进程从新程序的入口点(main()函数对应上述的入口地址)开始执行。 进程ID保持不变:虽然进程的内存和执行代码被替换,但进程的ID(PID)仍然是原进程的PID,进程的资源(如打开的文件缓冲区)默认不会改变,除非显式地进行操作。 注意的是之前进程所拥有的资源并不会被释放
2. 注意点
exec函数执行成功后永远不会返回,因为当前进程已被新进程替换 只有执行失败时才会返回-1,并设置errno 如果参数固定,使用execl/execlp 如果参数动态构建,使用execv/execvp
3. 相关函数和使用示例
# include <unistd.h>
int execl ( const char * path, const char * arg, . . . ) ;
int execlp ( const char * file, const char * arg, . . . ) ;
int execle ( const char * path, const char * arg, . . . , char * const envp[ ] ) ;
int execv ( const char * path, char * const argv[ ] ) ;
int execvp ( const char * file, char * const argv[ ] ) ;
int execvpe ( const char * file, char * const argv[ ] , char * const envp[ ] ) ;
execl
int main ( ) {
execl ( "/bin/ls" , "ls" , "-l" , "-a" , NULL ) ;
execl ( "./example.txt" , "example" , NULL ) ;
std:: cerr << "execl failed!" << std:: endl;
return 1 ;
}
excelp
execle
int execle ( const char * path, const char * arg, . . . , char * const envp[ ] ) ;
int main ( ) {
char * const envp[ ] = { "PATH=/bin" , "MY_VAR=HelloWorld" , NULL } ;
execle ( "/bin/ls" , "ls" , "-l" , NULL , envp) ;
std:: cerr << "execle failed!" << std:: endl;
return 1 ;
}
execv
将excel的参数装进了数组 允许通过参数数组来传递命令行参数
int execv ( const char * path, char * const argv[ ] ) ;
int main ( ) {
char * args[ ] = { "ls" , "-l" , NULL } ;
execv ( "/bin/ls" , args) ;
std:: cerr << "execv failed!" << std:: endl;
return 1 ;
}
execvp
int main ( ) {
char * args[ ] = { "ls" , "-l" , NULL } ;
execvp ( "ls" , args) ;
std:: cerr << "execvp failed!" << std:: endl;
return 1 ;
}
execvpe 类似execle
char * args[ ] = { "ls" , "-l" , NULL } ;
char * env[ ] = { "MY_VAR=HelloWorld" , "PATH=/bin" , NULL } ;
execvpe ( "ls" , args, env) ;
三、环境变量
在 Linux 系统中,环境变量(Environment Variables)是存储系统或用户配置的键值对,它们控制程序的行为或定义系统的特定设置。 环境变量通常用于存储系统路径、语言设置、终端配置等重要信息,影响程序的执行、外部命令的查找、文件路径的解析等。 它们的作用范围可以是全局的,也可以是针对特定用户或进程的。
1.环境变量分类
1.1系统环境变量
这些环境变量对所有用户和进程有效,通常由系统管理员或系统启动脚本设置。 有三个文件可以编辑,这三个文件中的配置都会影响系统范围内的所有用户,属于系统级的配置机制,但是它们的作用方式和适用场景有所不同
1.1.1/etc/environment
完全静态,只定义变量,没有脚本逻辑,因此可以直接归类为系统环境变量。 生效范围广,适用于所有用户和进程。 PATH 的顺序很重要,系统会按照从左到右的顺序查找可执行文件,因此如果同名命令在多个目录中存在,优先使用最左边的目录中的版本
这是我的环境变量
PATH= "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
添加的方式有两种
1. 在PATH的字符串里面加<< : 路径>>
2. 或者另起一行,一般这样做,看得出来被修改
PATH= "$PATH:/your/new/directory"
3. 保存重启即可生效,或者执行以下命令
source / etc/ environment
当然可以自定义添加一些环境变量,不过不推荐,这是系统级,少一点还是好。
格式为:MY_APP_HOME= "/opt/myapp"
1.1.2/etc/profile
在用户登录时运行,用于配置登录 shell 的全局环境变量。 全局作用:对所有用户的登录 shell 生效。 支持脚本:允许使用复杂的 shell 脚本(如条件语句、函数等)。 适用场景:通常用于设置需要动态计算的环境变量或初始化脚本。 仅对登录 shell 有效,非登录 shell(如子 shell)不加载 。
1.1.2.1登录和非登录的区别
特性 登录 Shell 非登录 Shell 启动方式 用户登录系统(ssh
、终端登录或 bash --login
) 打开终端仿真器或直接运行 bash
。 加载文件 /etc/profile
,~/.bash_profile
等全局配置文件仅加载 ~/.bashrc
(交互配置文件)。 使用场景 初始化用户环境,例如环境变量、语言、路径等 用于交互操作或运行脚本。 继承父进程变量 不完全继承,重新初始化环境变量 完全继承父 Shell 的环境变量。 是否交互式 可以是交互式或非交互式 通常是交互式,但也可用于脚本执行。
1. 定义全局环境变量
export JAVA_HOME= / usr/ lib/ jvm/ java- 11 - openjdk
export PATH= $JAVA_HOME/ bin: $PATH
所有用户登录时,都会加载这些变量。
不加export 只会生效于当前shell
注意可能与environment冲突
故export PATH= / custom/ path: $PATH # 添加到开头
# 或
export PATH= $PATH: / custom/ path # 添加到末尾
2. 加载其他配置条件
在/ etc/ profile. d/ 目录下 注意权限问题
以. sh 结尾的文件,注意谨慎使用和创建
2. 设置系统级别的别名
alias ll= 'ls -l'
alias df= 'df -h'
3. 定义全局函数
show_mem ( ) {
free - h
}
4. 设置默认权限掩码
umask 022 # 设置新建文件的默认权限
5. 配置系统提示符
export PS1= "\u@\h:\w\$ "
6. 系统启动时的招呼语
echo "Welcome to the system!"
6. 设置历史记录相关配置
export HISTSIZE= 1000
export HISTFILESIZE= 2000
export HISTTIMEFORMAT= "%Y-%m-%d %H:%M:%S "
1.1.3/etc/bash.bashrc
/etc/bash.bashrc 是 Bash shell 的全局配置文件 在 Bash Shell 会话中加载,尤其影响非登录 shell。也就是每次打开的终端
设置全局命令别名
alias ll= 'ls -l'
alias la= 'ls -la'
alias grep= 'grep --color=auto'
设置历史记录
# HISTSIZE: 设置当前 shell 会话中保存的最大历史命令条数
# 超过此条数后,最早的记录会被丢弃,仅对内存中的历史有效
HISTSIZE= 1000
# HISTFILESIZE: 设置 . bash_history 文件中保存的最大历史命令条数
# 超过此条数后,最早的记录会被丢弃,仅对磁盘文件中的历史有效
HISTFILESIZE= 2000
# HISTCONTROL: 控制命令历史记录的过滤规则
# ignoredups : 忽略连续重复的命令
# ignorespace : 忽略以空格开头的命令
# ignoreboth : 同时忽略上述两类命令
# erasedups : 删除历史中所有重复的命令,仅保留最后一次
HISTCONTROL= ignoredups
# HISTTIMEFORMAT: 设置显示命令历史时的时间戳格式
# 格式说明:
# % Y: 年份
# % m: 月份
# % d: 日期
# % H: 小时(24 小时制)
# % M: 分钟
# % S: 秒
# 时间戳仅在使用 `history` 查看时显示,不会存储到 . bash_history 文件中
HISTTIMEFORMAT= "%Y-%m-%d %H:%M:%S "
# 配置生效后,可通过 history 命令查看历史命令,效果如:
# 1 2024 - 11 - 30 12 : 30 : 00 ls
# 2 2024 - 11 - 30 12 : 31 : 10 pwd
启用补全功能
if [ - f / etc/ bash_completion ] ; then
. / etc/ bash_completion
fi
定义全局函数
历史记录 与 /etc/profile
的主要区别:
比较方面 /etc/profile
/etc/bash.bashrc
加载时机 登录 shell 时加载(如 SSH 登录) 每个新 bash shell 启动时都会加载 作用范围 适用于所有 shell 只适用于 bash shell 典型用途 主要设置环境变量 主要设置 shell 行为和交互特性
1.2用户级环境变量
仅适用于特定用户,由该用户单独设置。 存储在用户配置文件中,如 ~/.bashrc、~/.zshrc 或 ~/.profile。 格式固定,不能添加 shell 命令或函数
1.2.1 ~/.bashrc
~/.bashrc 是 Bash Shell 用户的配置文件,通常用于设置非登录 Shell 的环境和行为。它会在 每次启动非登录交互式 Shell 时自动加载 位置:每个用户都有自己的 ~/.bashrc 文件,位于用户的主目录下。save是备份哈 具体用法
定义环境变量。
export PATH= $PATH: / custom/ path
export EDITOR= vim
export LANG= en_US. UTF- 8
配置命令别名。
alias ll= 'ls -alF'
alias la= 'ls -A'
alias l= 'ls -CF'
自定义提示符(Prompt)。
export PS1= "\u@\h:\w\$ "
\u:用户名。
\h:主机名。
\w:当前工作目录。
\$:提示符字符(普通用户为 $,超级用户为 #)。
配置 Shell 行为(如历史记录、自动补全等)
启用shell功能
shopt - s checkwinsize # 自动调整终端大小
shopt - s autocd # 允许直接输入目录名称进行切换
shopt - s cdspell # 自动纠正拼写错误的目录名称
设置函数
function mkcd ( ) {
mkdir - p "$1" && cd "$1"
}
加载时机
打开终端仿真器(如 GNOME Terminal、Konsole)。 运行非登录的交互式 Bash Shell 被登录 Shell 显式调用(通过在 ~/.bash_profile 中引入 ~/.bashrc)
1.2.2~/.profile
~/.profile 是一个用户级的配置文件,用于定义登录 Shell 的环境设置。它主要在用户登录系统时被加载,并为用户会话设置默认的环境变量和系统行为。 位置:位于用户的主目录下(~/.profile) 主要用法
设置全局环境变量(例如 PATH、LANG)。
配置用户的启动环境。
调用其他配置文件(如 ~ / . bashrc)。
加载时机
用户通过登录 Shell 登录系统 作为其他配置文件的备用 - 如果 ~/.bash_profile 或 ~/.bash_login 文件不存在,则 ~/.profile 会被登录 Shell 加载 对于非登录 Shell(如直接打开终端仿真器),~/.profile 不会自动加载。 加载优先级,找到第一个即停止
~/.bash_profile ~/.bash_login ~/.profile
1.2.3~/.bash_logout
1.3会话级环境变量
仅在当前会话(例如一个终端窗口)中有效,通常通过临时命令(如 export)设置。 使用以下命令查看当前会话中的环境变量printenv或env 特定变量值
echo $VAR_NAME 查看特定变量
unset VAR_NAME 使用 unset 删除会话中的变量
bash
exit
export SHARED_VAR= "hello"
bash
echo $SHARED_VAR # 子进程中可以访问 SHARED_VAR
# 设置普通变量
TEST_VAR= "hello"
# 启动子进程(新的shell)
bash
echo $TEST_VAR # 输出为空,子进程无法访问
# 直接使用 set 定义变量 (默认情况下,使用 set 定义的变量是局部变量,不会被子进程继承。)
set VAR_NAME= value
# 临时设置代理
export http_proxy= "http://127.0.0.1:7890"
export https_proxy= "http://127.0.0.1:7890"
# 临时修改语言环境
export LANG= "en_US.UTF-8"
# 临时修改编辑器
export EDITOR= "vim"
配置临时路径
export PATH= $PATH: / temporary/ path
设置调试参数(为程序运行临时设置调试环境变量)
export DEBUG= true
临时禁用功能
export HISTSIZE= 0
直接使用 set 定义变量 (默认情况下,使用 set 定义的变量是局部变量,不会被子进程继承。)
set VAR_NAME= value
1.4归纳
类别 生效范围 优先级 生效时间 典型用途 系统环境变量 全局(所有用户) 低 系统启动后长期生效 配置系统关键参数(如路径) 用户级环境变量 单用户 中 用户登录后长期生效 配置用户个性化参数 会话级环境变量 当前终端或进程 高 当前会话,关闭即失效 临时调整变量(如调试模式)
2. 常见环境变量
环境变量 描述 HOME
当前用户的主目录路径 USER
当前用户的用户名 LOGNAME
当前登录用户的用户名 SHELL
当前使用的 shell 类型(如 /bin/bash
) PATH
可执行文件的搜索路径 LANG
系统的默认语言和区域设置 LANGUAGE
可接受的语言顺序 LC_*
各种区域设置(如 LC_TIME
、LC_NUMERIC
、LC_CTYPE
等) DISPLAY
指定 X11 显示的显示设备(如 :0
) TERM
当前终端类型(如 xterm-256color
) PWD
当前工作目录 EDITOR
默认的文本编辑器(如 vim
、nano
) HISTSIZE
Bash shell 中保存的历史命令数量 SSH_AUTH_SOCK
SSH 认证代理的 socket 路径 PS1
提示符的格式化字符串 XDG_SESSION_TYPE
当前会话类型(如 x11
或 wayland
) XDG_SESSION_ID
当前会话的 ID XDG_CONFIG_DIRS
配置文件搜索路径,通常包含 /etc/xdg
XDG_RUNTIME_DIR
当前会话的运行时目录 TERM_PROGRAM
当前终端程序的类型(如 Apple_Terminal
或 gnome-terminal
) QT_IM_MODULE
Qt 使用的输入法模块 LC_CTYPE
定义字符分类行为的区域设置(如字符编码) LC_TIME
时间和日期格式的区域设置 LC_NUMERIC
数字格式的区域设置 LC_MONETARY
货币格式的区域设置 LC_PAPER
纸张大小的区域设置 LC_ADDRESS
地址格式的区域设置 LD_LIBRARY_PATH
动态库搜索路径 TMPDIR
临时文件存储目录
四.set指令
内置命令,用于配置和显示 Shell 的环境选项、变量和参数。它是一个功能非常强大的工具,可以控制 Shell 的行为、设置位置参数、显示环境变量等。
1.基本功能
set # 显示所有变量和函数 set -o # 查看所有 shell 选项设置 set +o # Shell 选项会以一种可以直接写入脚本的格式输出
设置
开启:set -o xxx:启用选项 关闭:set +o xxx:禁用选项 选项功能
选项 状态 作用 allexport off
如果打开(on
),所有定义的变量会自动通过 export
成为环境变量。 braceexpand on
启用大括号扩展,例如 {a,b,c}
扩展为 a b c
。 emacs on
启用 Emacs 风格的命令行编辑模式,支持 Ctrl+A
、Ctrl+E
等快捷键。 errexit off
如果打开(on
),脚本中命令出错(返回非零状态)会导致脚本立即退出。 errtrace off
如果打开(on
),允许在函数或子 shell 中捕获 ERR
信号(错误处理)。 functrace off
如果打开(on
),允许函数继承 DEBUG
和 RETURN
trap(调试功能)。 hashall on
启用命令路径的哈希缓存,加快命令查找速度。 histexpand on
启用命令历史扩展功能,如使用 !
调用历史命令(!!
、!123
等)。 history on
启用命令历史记录功能,可通过 history
查看和调用历史命令。 ignoreeof off
如果打开(on
),禁止通过 Ctrl+D
退出 shell,必须使用 exit
命令。 interactive-comments on
允许在交互式 shell 中使用 #
注释。 keyword off
如果打开(on
),允许在 shell 脚本中直接使用 shell 关键字功能。 monitor on
启用作业控制功能(支持后台运行、Ctrl+Z
暂停、fg
恢复等)。
2.常用选项
set -x 和 set +x 是 Bash 的调试工具,用于控制调试模式的启用和关闭。这些命令非常有用,尤其是在开发和调试 Bash 脚本时,能帮助定位问题或跟踪脚本执行过程。
set -x:用调试模式
显示命令执行过程:在调试模式下,Bash 会打印每条执行的命令及其参数。 用于检查脚本的执行流程。 帮助排查脚本中的逻辑错误或未预期的行为。 举例 #! / bin/ bash
# 显示行号
set - n
echo "Step 1: No debugging here"
set - x
echo "Step 2: Debugging starts"
ls / etc/ passwd
echo "Step 3: Debugging ends"
set + x
echo "Step 4: Back to normal execution"
执行结果
Step 1 : No debugging here
+ echo 'Step 2: Debugging starts'
Step 2 : Debugging starts
+ ls / etc/ passwd
/ etc/ passwd
+ echo 'Step 3: Debugging ends'
Step 3 : Debugging ends
Step 4 : Back to normal execution
如下
命令 作用 场景 set -x
启用调试模式,显示执行的每条命令及其参数。 调试脚本执行流程,帮助快速定位问题。 set +x
关闭调试模式,恢复默认状态。 调试完成后关闭,避免输出过多信息。 set -e
遇到错误(命令返回非零状态)时立即退出脚本。 防止脚本在错误状态下继续执行,避免产生更严重的后果。 set +e
关闭立即退出功能。 在容错性较高的脚本中,允许部分命令出错而不退出整个脚本。 set -u
使用未定义变量时报错并退出脚本。 强制检查变量是否定义,避免因拼写错误或缺少变量而导致的潜在问题。 set +u
关闭未定义变量检查功能。 脚本中可能存在合法的未定义变量或默认值,关闭检查以避免误报。 set -o noclobber
防止重定向覆盖已有文件(如 >
)。 保护关键文件,避免因误操作覆盖重要数据。 set +o noclobber
允许重定向覆盖文件(默认行为)。 需要在脚本中覆盖文件时使用。 set -v
显示脚本执行前的原始代码(逐行打印)。 用于检查脚本逻辑或语法问题,配合 -x
使用效果更佳。 set +v
关闭原始代码显示功能。 执行完成后关闭,保持输出整洁。 set -o pipefail
如果管道中的任意命令失败,则整个管道返回失败。 确保管道中所有命令都成功执行,避免后续操作依赖错误的中间结果。 set +o pipefail
关闭管道失败传播功能(默认行为)。 允许管道中的某些命令失败而不影响整个脚本执行。
常见用法
# 脚本开头的安全设置
set - euo pipefail
# 等同于:
set - e # 出错时退出
set - u # 使用未定义变量时报错`在这里插入代码片`
set - o pipefail # 管道中的错误也会导致退出
或者
set - euxo pipefail # 启用调试、错误检查、未定义变量检查和管道错误传播
3.特殊用法
格式:set -- [ 参数1 ] [ 参数2 ] [ 参数3 ] . . .
参数1 、参数2. . . :依次设置为位置参数 $1 、$2 、$3 等
例如
set -- hello world bash
echo $1 # 输出 hello
echo $2 # 输出 world
echo $3 # 输出 bash