文章目录

  • Shell基础
    • Shell本身
    • Shell脚本
    • 第一个Shell脚本
    • 运行Shell脚本有三种方式
    • Shell bash和sh区别
    • .sh文件与.bash文件
  • Shell内置变量命令
    • eval
    • echo
    • 实例分析
  • .sh脚本自动执行文件
    • 一个.sh执行多个程序
    • 执行多个.sh

Shell基础

Shell本身

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。

Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。

shell 是用户登录时看到的主界面,用来启动其他应用程序。

在 UNIX 圈子中,shell 专门用于表示命令行 shell,以输入想要启动的应用程序名,后面跟随想要操作的文件或其他对象的名称,按下 Enter 键。其他非 UNIX 的环境不用 shell 这个词;基于视窗界面的操作系统使用“窗口管理器”和“桌面环境”而不是 shell。

有很多种不同的 UNIX shell。常见的包括 bash(大多数 Linux 预装)、zsh(强大且可随心定制)、fish(更强调简洁)

Shell脚本

Shell 脚本(shell script),是一种为 shell 编写的脚本程序。

业界所说的 shell 通常都是指 shell 脚本,但读者朋友要知道,shell 和 shell script 是两个不同的概念。

由于习惯的原因,简洁起见,本文出现的 “shell编程” 都是指 shell 脚本编程,不是指开发 shell 自身。

Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。

Linux 的 Shell 种类众多,常见的有:

  1. Bourne Shell(/usr/bin/sh或/bin/sh)
  2. Bourne Again Shell(/bin/bash)
  3. C Shell(/usr/bin/csh)
  4. K Shell(/usr/bin/ksh)
  5. Shell for Root(/sbin/sh)

本教程关注的是 Bash,也就是 Bourne Again Shell,由于易用和免费,Bash 在日常工作中被广泛使用。同时,Bash 也是大多数Linux 系统默认的 Shell。

在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为 #!/bin/bash。

#! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。

第一个Shell脚本

打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 test.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用 php 写 shell 脚本,扩展名就用 php 好了。

输入一些代码,第一行一般是这样:

#!/bin/bash
echo "Hello World !"

#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。

echo 命令用于向窗口输出文本。

回车换行导致command not found:习惯用回车使代码变得清晰,但是会让shell脚本输出:command not found

#!/bin/bashecho "Hello World !"


解决:

sublime text

View->Line endings->Unix

editplus

Document->File Fomart(FR/LF)->Change File Format

MobaTextEditor

Format -> UNIX

运行Shell脚本有三种方式

1、作为可执行程序

将上面的代码保存为 test.sh,并 cd 到相应目录:

chmod +x ./test.sh  #使脚本具有执行权限
./test.sh  #执行脚本

注意,一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。

2、作为解释器参数

这种运行方式是,直接运行解释器,其参数就是 shell 脚本的文件名,如:

/bin/sh test.sh
/bin/php test.php

这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。

3、直接用sh(这种办法不需要文件具备可执行的权限也可运行)

sh ./test.sh

Shell bash和sh区别

sh 遵循POSIX规范:“当某行代码出错时,不继续往下解释”。bash 就算出错,也会继续向下执行。

POSIX表示可移植操作系统接口(Portable Operating System Interface of UNIX,缩写为 POSIX )。POSIX标准意在期望获得源代码级别的软件可移植性。换句话说,为一个POSIX兼容的操作系统编写的程序,应该可以在任何其它的POSIX操作系统上编译执行。

sh 脚本:

#!/bin/sh
source err
echo "test sh"

结果为:
testsh.sh: 2: testsh.sh: source: not found

bash 脚本:

#!/bin/bash
source err
echo "test sh"

结果为:
testsh.sh: 2: testsh.sh: source: not found
test sh

sh 跟bash的区别,实际上是bash有没开启POSIX模式的区别。

简单说,sh是bash的一种特殊的模式,sh就是开启了POSIX标准的bash, /bin/sh 相当于 /bin/bash --posix。

.sh文件与.bash文件

.sh文件和.bash文件都是脚本文件,.sh文件对应shell解释器,.bash对应bash解释器。大多数情况下,两者可以视为相同。

Shell内置变量命令

eval

命令格式:eval args
功能:当Shell程序执行到eval语句时,Shell读入参数args,并将它们组合成一个新的命令,然后执行。

[root@zabbix ~]# cat eval.sh
echo $1 $2          -- 打印输出第一第二个参数
echo $#             -- 打印输出参数个数
eval "echo \$$#"  -- 二次解析"echo $2"为一个命令,输出结果
[root@zabbix ~]# sh eval.sh arg1 arg2
arg1 arg2
2
arg2

eval “$(conda shell.bash hook)” : 用shell脚本激活conda虚拟环境

echo

命令格式:echo args #<==可以是字符串和变量的组合。功能说明:将echo命令后面args指定的字符串及变量等显示到标准输出。

实例分析

#!/bin/sh## uncomment for slurm
##SBATCH -p gpu
##SBATCH --gres=gpu:8
##SBATCH -c 80export PYTHONPATH=./
eval "$(conda shell.bash hook)"
##conda activate yolo_hx  # pytorch 1.4.0 env
PYTHON=pythondataset=$1
exp_name=$2
exp_dir=exp/${dataset}/${exp_name}
model_dir=${exp_dir}/model
result_dir=${exp_dir}/result
config=config/${dataset}/${dataset}_${exp_name}.yaml
now=$(date +"%Y%m%d_%H%M%S")mkdir -p ${model_dir} ${result_dir}
cp tool/train.sh tool/train.py tool/test.sh tool/test.py ${config} ${exp_dir}export PYTHONPATH=./
$PYTHON -u ${exp_dir}/train.py \--config=${config} \2>&1 | tee ${model_dir}/train-$now.log

A. python -u:python执行脚本输出到屏幕结果直接重定向到日志文件的情况下,使用-u参数,这样将标准输出的结果不经缓存直接输出到日志文件。

B. 2>&1 | tee train-$now.log t命令解析

2>&1应该分成两个部分来看,一个是2>以及另一个是&1,

其中2>就是将标准出错重定向到某个特定的地方;&1是指无论标准输出在哪里。

所以2>&1的意思就是说无论标准出错在哪里,都将标准出错重定向到标准输出中。

有时候希望将错误的信息重新定向到输出,就是将2的结果重定向至1中就有了”2>1”这样的思路,如果按照上面的写法,系统会默认将错误的信息(STDERR)2重定向到一个名字为1的文件中,而非所想的(STDOUT)中。因此需要加&进行区分。就有了 2>&1 这样的用法

| 管道

管道的作用是提供一个通道,将上一个程序的标准输出重定向到下一个程序作为下一个程序的标准输入。

通常使用管道的好处是一方面形式上简单,另一方面其执行效率要远高于使用临时文件。

这里使用管道的目的是将make程序的输出重定向到下一个程序,其最终目的是用来将输出log存入文件中。

tee是用来干什么的?

tee从标准输入中读取,并将读入的内容写到标准输出以及文件中。

所以这里tee命令的作用是将数据读入并写到标准输出以及log.txt中。

之所以要将编译产生的log保存到log.txt中,其原因是你的标准输出的缓存可能是有限制的,而你编译程序产生的log可能会很多,这样很可能会造成log不完整;

其目的是当程序发生编译错误的时候,我们可以从log.txt中看到完整的编译log,这样方便查找编译错误。

C. PYTHONPATH=./ 的作用
将当前所处文件加入系统环境中

.sh脚本自动执行文件

有时候我需要很多超参数参数,跑出来的实验结果。这个时候比如我有两张卡,要跑十个实验,我可以预先设定好超参数并且写到.sh文件里,就可以实现这个程序执行完自动执行下一个,而不用人盯着结束了再放到卡上跑(因为一张GPU同时加速两个程序,没有一个一个放上去快,在利用率都占满的情况下)

一个.sh执行多个程序

在一个.sh文件里,$!来表示后台运行的最后一个进程的 ID 号,同时挂到后台后,wait挂到后台的进程,两个结束后才进行下面的操作。

python Vgg16_CIFAR100.py --device 0  --lr 0.1 &
PID1=$!;
python Vgg16_CIFAR100.py --device 1  --lr 0.01 &
PID2=$!;
wait ${PID1} && wait ${PID2}python ResNet20_CIFAR100.py --device 0  --lr 0.1 &
PID1=$!;
python ResNet20_CIFAR100.py --device 1  --lr 0.01 &
PID2=$!;
wait ${PID1} && wait ${PID2}

执行多个.sh

1. Shell 教程
2. shell—解决shell脚本中回车换行导致command not found
3. Shell bash和sh区别
4. shell内置变量命令:echo、eval、exec、export、read、shift
5. Shell 输入/输出重定向
6. Linux添加PYTHONPATH方法以及3种修改环境变量方法
7. Shell 脚本中 ‘$’ 符号的多种用法
8. Shell(Bash)多命令顺序执行方法详解

【Linux中shell命令】.sh文件种种操作相关推荐

  1. Linux中shell命令的用法和技巧

    使用Linux shell是我每天的基本工作,但我经常会忘记一些有用的shell命令和l技巧.当然,命令我能记住,但我不敢说能记得如何用它执行某个特定任务.于是,我开始在一个文本文件里记录这些用法,并 ...

  2. linux常用shell命令之文件操作命令

    # touch 新建空文件,或更新文件时间标记 touch path/filename user@computer: ~$ touch myfile # 在当前目录下新建myfile user@com ...

  3. Linux 中 cp 命令(文件复制)

    cp命令用来将一个或多个源文件或者目录复制到指定的目的文件或目录.它可以将单个源文件复制成一个指定文件名的具体的文件或一个已经存在的目录下.cp命令还支持同时复制多个文件,当一次复制多个文件时,目标文 ...

  4. Unix/Linux 中shell命令 awk

    shell命令awk使用例: 通过脚本打印出系统当前内存使用的百分比: #!/bin/bash [centos@centos shell]$ free -mtotal used free shared ...

  5. linux 增量 cp,Linux 中 cp 命令(文件复制)

    cp命令用来将一个或多个源文件或者目录复制到指定的目的文件或目录.它可以将单个源文件复制成一个指定文件名的具体的文件或一个已经存在的目录下.cp命令还支持同时复制多个文件,当一次复制多个文件时,目标文 ...

  6. C++|Linux工作笔记-C++获取Linux中shell命令结果

    目录 基本概念 代码与实例 基本概念 这里首先介绍一条Linux函数: ps -ef | awk '{print $2,$8,$9,$10}' 这个可以当前Linux系统运行的进程 另外一个知识点: ...

  7. 如何在linux上压缩文件夹,如何在Linux中使用命令压缩文件和文件夹

    通常情况下,我们都是安装了zip,但验证一下也无妨.你可以运行下面的命令来安装zip sudo apt install zip unzip 现在你知道你的系统支持zip了,你可以继续阅读学习如何在Li ...

  8. linux中shell命令行缩进,Linux下几个实用的bash命令 | 旺旺知识库

    一.扩展字段匹配 首先我们来看一个叫做扩展字段匹配的功能.这个选项允许你执行比标准Bash所提供的更复杂的字段匹配.例如,你可以定位除了后缀为.tmp之外的所有文件.扩展字段匹配功能可以通过shopt ...

  9. Linux中vi命令编辑文件时显示行号

    vi file_name 直接进去时没有行号显示的,这时可以进入末行模式(文件末尾出现冒号)时输入 : set nu 效果如图: 这种做法有个弊端,在退出编辑后,再次进入编辑时行号就不再显示了. 配置 ...

最新文章

  1. 应用缓存的基本概念,香(Redis)
  2. oracle 监听程序当前无法识别连接描述符中请求的服务_Go 中的优雅升级
  3. Liferay 6.1 用maven 构建 service-builder的巨大BUG的修复
  4. 833 计算机学科专业基础综合,2017年西安电子科技大学计算机学院833计算机学科专业基础综合考研仿真模拟题...
  5. 用javah 导出类的头文件, 常见的错误及正确的使用方法
  6. JVM:永久代 以及jdk1.8为什么将其移除?
  7. NokiaJ2ME开发者套件4.0 J2ME 开发
  8. QT的QDBusVariant类的使用
  9. mysql的service name_安装MYSQL出错:a windows service with the name MYSQL already...service解决...
  10. 2015英特尔® 实感™ (Intel® RealSense™) 动手开发实验课
  11. 桥式整流以及电容作用
  12. Java后台生成NO2016012701(代码+年月日+流水号)这样的流水编号
  13. lpx寒假作业案例11
  14. Redefinition of typedef is a C11 feature
  15. HDU 6441(费马大定理+奇偶数列法)
  16. C#大作业(FPS大型单机游戏)笔记简记
  17. 【tensorrt】——Network has dynamic or shape inputs, but no optimization profile has been defined.
  18. 基于srs流媒体服务器搭建gb28181视频平台的微服务系统架构
  19. 阿里云服务器创建快照、回滚磁盘
  20. Camera - dump 预览帧数据处理(三)

热门文章

  1. 积极准备、谨慎行动——应对多核编程革命
  2. PDF怎么编辑?如何在PDF上直接修改或删除?
  3. 修改mongodb最大查询数_根据Mongodb查询中的一个字段查找最大连续记录数
  4. 空间环境和地形特征的模拟
  5. Linux系统安装Hadoop
  6. 使用js cookie实现自动登录
  7. 美通企业日报 | 中国新车质量问题数明显减少;阿迪达斯大中华区二季度销售额大增...
  8. F4V怎么转换MP4,F4V在线转MP4
  9. 用java写表白神器_用 Python 写个七夕表白神器
  10. 学会数据分析,帮你工作效率翻倍,告别加班!