本文主要是介绍Shell 基本笔录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 神秘代码
- 获取 OS Kernel CPU MEM DISK 信息
- 第一行代码
- 全局运行
- 开机启动
- systemctl
- rc.local
- gnome-session-properties
- 后台运行
文中涉及的脚本主要在 虚拟机 和 Jetson TX2 中的Ubuntu18
进行测试
神秘代码
一些 字体颜色 加粗 清屏 等的神秘代码, 其实是一些控制选项, 如echo
的-e
参数可以 启用反斜杠转义的解释
参考:
- Git shell coloring (github.com)
- shell脚本中echo显示内容带颜色 - lr_ting - 博客园 (cnblogs.com)
#!/bin/bash# 0 Regular
# 1 Bold, Highlight?
# 2 Dark
# 3 Italic
# 4 Underline# \033[30m — \33[37m, Foreground Color
# \033[0m Text Reset# Regular Colors, Bold+Italic+Underline
echo -e "\033[30m Black \033[0m", "\033[1;3;4;30m Black \033[0m"
echo -e "\033[31m Red \033[0m", "\033[1;3;4;31m Red \033[0m"
echo -e "\033[32m Green \033[0m", "\033[1;3;4;32m Green \033[0m"
echo -e "\033[33m Yellow \033[0m", "\033[1;3;4;33m Yellow \033[0m"
echo -e "\033[34m Blue \033[0m", "\033[1;3;4;34m Blue \033[0m"
echo -e "\033[35m Purple \033[0m", "\033[1;3;4;35m Purple \033[0m"
echo -e "\033[36m Cyan \033[0m", "\033[1;3;4;36m Cyan \033[0m"
echo -e "\033[37m White \033[0m", "\033[1;3;4;37m White \033[0m"
运行显示效果如下, 左边为规则字体0, 右边为 加粗1, 斜体3, 加下划线4 的效果
几种清屏的命令
# https://stackoverflow.com/questions/5367068/clear-a-terminal-screen-for-real
clear # Clean the visible screen
clear && clear # Clean screen and clear bufferprintf "\033c" # 在c语言中为 printf("\033c");
printf "\x1bc"
printf "\u001bc"
printf "\ec" # \e is ESC in bash# 可以起别名
alias cls='printf "\033c"'
clsecho -en "\ec" #thanks @Jonathon Reinhart.
# -e Enable interpretation of of backslash escapes
# -n Do not output a new line# \033[0;0H光标设置(y,x)=(0,0), 清屏\033[2J
echo -en "\033[0;0H\033[2J" reset # Clean and 1-sec delay
tput reset # Clean without 1-sec delay# 也可以键盘按下 Ctrl + L
获取 OS Kernel CPU MEM DISK 信息
主要是 grep, awk
命令, 可以参考screenfetch, jtop
之类的开源代码
#!/bin/bash# OS: Ubuntu 18.04 bionic
echo -en "\033[1;31mOS: \033[0m"
# 也可以从`lsb_release -a`里面裁
LSB_RELEASE=`cat /etc/lsb-release`
# echo $LSB_RELEASE为单行, 加""为多行
# DISTRIB_ID=Ubuntu, 用=分割, 取出第2个元素, $2可换成最后一个Filed: $NF
echo "$LSB_RELEASE" | grep DISTRIB_ID | awk -F '=' '{printf "%s ", $2}'
# DISTRIB_DESCRIPTION="Ubuntu 18.04.6 LTS", 默认空格分割, 取倒数第二个
echo "$LSB_RELEASE" | grep DISTRIB_DESCRIPTION | awk '{printf "%s ", $(NF-1)}'
# DISTRIB_CODENAME=bionic
echo "$LSB_RELEASE" | grep DISTRIB_CODENAME | awk -F '=' '{print $2}'# Kernel: 5.4.0-91-generic
echo -en "\033[1;31mKernel: \033[0m"
echo `cat /proc/sys/kernel/osrelease`# CPU
# cat /proc/cpuinfo | grep -E 'processor|model name'
# cat /proc/cpuinfo | grep -iE 'processor|model name|CPU part'
# 也可以用折叠的 cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
echo -e "\033[1;31mCPU: \033[0m"
CPU_INFO=`cat /proc/cpuinfo`
# processor : 0
# model name : Intel(R) Core(TM) i7-8086K CPU @ 4.00GHz
echo "$CPU_INFO" | grep -E 'processor|model name' | awk -F':' '{printf "%s",$NF} NR % 2 == 0 {print ""}'# MEM
# cat /proc/meminfo
# MemTotal: 16369576 kB
echo -en "\033[1;31mMEM: \033[0m"
MEM_INFO=`cat /proc/meminfo`
echo "$MEM_INFO" | grep MemTotal | awk '{printf "%.1f GB\n", $(NF-1)/1024/1024}'# DISK
echo -en "\033[1;31mDISK: \033[0m"
echo `df -H / | tail -1 | awk '{printf "%sB, used %sB\n", $2, $3}'`
虚拟机测试结果如下
TX2测试结果(sudo nvpmodel -m 0
)如下
其中, CPU的参数人性化显示是最不好搞的:
- 要考虑 同构/异构, 酷睿系列固然一致, 但如Jetson TX2, 是
A57*4+D15*2
, 手机中的处理器的异构更是常见 - ARM的代号不是我们常见的A57/A72这种, 如
0xd07 是 Cortex-A57
, 还要经过翻译或者查表工作, 新来的RISCV之类的不懂也不知道啥情况 - 要考虑功耗, 如果CPU被关掉, 很可能查不出来, 如下面的例子
# jetson TX2 默认功耗模式3, 只能看到4个A57
$ cat /proc/cpuinfo | grep -iE 'processor|model name|CPU part'
processor : 0
model name : ARMv8 Processor rev 3 (v8l)
CPU part : 0xd07
processor : 3
model name : ARMv8 Processor rev 3 (v8l)
CPU part : 0xd07
processor : 4
model name : ARMv8 Processor rev 3 (v8l)
CPU part : 0xd07
processor : 5
model name : ARMv8 Processor rev 3 (v8l)
CPU part : 0xd07# https://en.wikipedia.org/wiki/Comparison_of_ARMv8-A_cores
# 0xd07 是 Cortex-A57# 设置功耗模式0, 可以看到4*A57+2*D15
$ sudo nvpmodel -m 0
$ cat /proc/cpuinfo | grep -iE 'processor|model name|CPU part'
processor : 0
model name : ARMv8 Processor rev 3 (v8l)
CPU part : 0xd07
processor : 1
model name : ARMv8 Processor rev 0 (v8l)
CPU part : 0x003
processor : 2
model name : ARMv8 Processor rev 0 (v8l)
CPU part : 0x003
processor : 3
model name : ARMv8 Processor rev 3 (v8l)
CPU part : 0xd07
processor : 4
model name : ARMv8 Processor rev 3 (v8l)
CPU part : 0xd07
processor : 5
model name : ARMv8 Processor rev 3 (v8l)
CPU part : 0xd07
第一行代码
参考 Shell 教程 | 菜鸟教程 (runoob.com)
Linux的Shell脚本解释器很多, 常见的有:
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- Shell for Root(/sbin/sh)
- …
一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh
,它同样也可以改为 #!/bin/bash
.
#!
告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序, 类似的还有指定python3
运行的 #!/usr/bin/python3
如我们新建1.py
print('py3 abc')
用python3运行没有问题, 但是直接运行会报错:
$ python 1.py
py3 abc
$ chmod 777 1.py
$ ./1.py
./1.py: line 1: syntax error near unexpected token `'py3 abc''
./1.py: line 1: `print('py3 abc')'
我们就在第一行指定python3运行
# 先看python3在哪里
$ which python3
/usr/bin/python3# 加入第一行代码 #!/usr/bin/python3
$ vi 1.py
#!/usr/bin/python3
print('py3 abc')# 然后就可以直接运行了
$ ./1.py
py3 abc
那我如果第一行留空, 第二行再加#!/usr/bin/python3
行不行呢? 如下图
是运行不了的:
$ ./1.py
./1.py: line 3: syntax error near unexpected token `'py3 abc''
./1.py: line 3: `print('py3 abc')'
所以, shell脚本别忘了第一行加上 #!/bin/bash
或 #!/bin/sh
, python3脚本也最好在开头加上 #!/usr/bin/python3
(windows下的情况可能不一样, 这里不讨论)
全局运行
先来看下默认的全局PATH:
# 虚拟机中
$ echo $PATH | awk -F':' '{for(i=1;i<=NF;i++){print $i}}'
/home/d/.local/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin# TX2中
$ echo $PATH | awk -F':' '{for(i=1;i<=NF;i++){print $i}}'
/opt/ros/melodic/bin
/usr/local/cuda-10.2/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
现在~/shell
路径下有脚本 abc.sh
, 已加权限777
#!/bin/bash
echo "abc"
如果想打开一个终端, 不用切换路径, 就可以运行, 有N种方法, 这里介绍下常用的
把脚本文件目录加到环境变量中, 默认的全局变量可以通过修改文件 /etc/profile
或者我们熟悉的ros放置的用户目录的 ~/.bashrc
添加, 以后面的为例
# 把脚本所在目录 /home/d/shell 加到环境变量中
# >> 是追加的意思
$ echo -e "\nexport PATH=\$PATH:/home/d/shell" >> ~/.bashrc
# 不打开新终端就 source ~/.bashrc
# 这样每次打开新终端, PATH变量就会自动加上/home/d/shell
# 然后在其它目录也可以直接运行 abc.sh
d@ubuntu:~$ abc.sh
abc
把脚本移动到PATH包含的目录中, 如把脚本放到 /usr/local/bin
里面(主要是这个目录比较空), 这里重命名为xyz.sh
$ sudo mv ~/shell/abc.sh /usr/local/bin/xyz.sh
# 然后就可以直接运行
d@ubuntu:~$ xyz.sh
abc
如果连.sh后缀也不想要, 直接xyz
运行
d@ubuntu:~$ sudo mv /usr/local/bin/xyz.sh /usr/local/bin/xyz
d@ubuntu:~$ xyz
abc
d@ubuntu:~$ which xyz
/usr/local/bin/xyz
实际上, python3的文件也可以这么搞, 第一行加上 #!/usr/bin/python3
, 用chmod
加上执行权限, 文件去掉.py
后缀, 放到/usr/local/bin
下面, 也可以直接运行了, 就像装了一个APP一样
开机启动
主推systemctl
, 或者用这个机制实现的rc.local
systemctl
分三步:
- 写脚本
- 写service
- 启动service
######################################################
# 写脚本 /home/karoto/ha/ha.sh
# #!/bin/sh必须添加
# 写完后加执行权限 sudo chmod a+x ha.sh
# 注意 echo 'the history process' > /dev/kmsg 这个只有root可以执行#!/bin/sh
echo 'the history process' > /dev/kmsg######################################################
# 写service
# sudo vi /etc/systemd/system/ha.service[Unit]
Description=ha
[Service]
ExecStart=/home/karoto/ha/ha.sh start
[Install]
WantedBy=multi-user.target######################################################
# 启动service
sudo systemctl daemon-reload
sudo systemctl enable ha.service
sudo systemctl start ha.service######################################################
# 检验service
sudo systemctl status ha.service
sudo reboot
dmesg | grep -i 'the history process'######################################################
# 清理service
sudo systemctl daemon-reload
sudo systemctl stop ha.service
sudo systemctl disable ha.service
sudo rm -f /etc/systemd/system/ha.service
rc.local
其实还是systemctl的原理, 让rc.local开机启动, 然后我把启动脚本的命令放到rc.local里就可以了
######################################################
# 写脚本 /home/karoto/ha/ha.sh
# 加执行权限 sudo chmod a+x ha.sh#!/bin/sh
echo 'the history process' > /dev/kmsg######################################################
# 添加到rc.local
# sudo vi /etc/rc.local
# #!/bin/sh 不能少
# 添加权限 sudo chmod 777 /etc/rc.local#!/bin/sh -e
/home/karoto/ha/ha.sh &######################################################
# 写rc-local.service
# sudo vi /etc/systemd/system/rc-local.service[Unit]
Description=/etc/rc.local Compatibility
Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=/etc/rc.local
After=network.target[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
RemainAfterExit=yes
GuessMainPID=no[Install]
WantedBy=multi-user.target
Alias=rc-local.service######################################################
# 启动rc-local.service
sudo systemctl daemon-reload
sudo systemctl enable rc-local
sudo systemctl start rc-local.service######################################################
# 检验service
sudo systemctl status rc-local.service
sudo reboot
dmesg | grep -i 'the history process'######################################################
# 清理脚本
# rc-local.service就保留下来, 只删除启动的脚本
# sudo vi /etc/rc.local
# 删除 /home/karoto/ha/ha.sh
gnome-session-properties
这种方式有图形界面, 比较简单, 但上面需要root权限运行的ha.sh在这里是运行不了的.
# 创建一个脚本 /home/karoto/ha/he.sh
# 加权限 sudo chmod a+x he.sh#!/bin/sh
mkdir /home/karoto/ha/he
命令行输入 gnome-session-properties
添加为启动脚本
重启 sudo reboot
, 可以看到/home/karoto/ha
多了he
文件夹.
想删除的话, gnome-session-properties
选中, 点击Remove
按钮删除即可
后台运行
后台运行脚本是很有必要的, 比如:
roscore
占用一个会话, 挪到后台会清爽很多- 很多服务器或者控制器, 如华为的MDC, 基本不用或没有显示接口, 只能ssh连上去, 如果笔记本运行一个前台脚本, 只要拔掉网线, 运行就会中断, 这是不行的
- 一些会话一直打印一些日志, 放到后台, 需要看的时候再调出来, 会清爽很多
- …
关键词 如 &, nohup, GNU screen, tmux, byobu, Terminator等, 或者中文搜索 终端复用器. 常见的有 screen(内部快捷键占用ctrl + a) 和 tmux (内部快捷键默认占用ctrl + b) , 一般都需要 sudo apt install
安装, 这里简要介绍下 tmux.
不看window, 先只看下tmux的session操作:
tmux new -s my_session
, 创建并进入名为my_session的会话tmux new -s my_session -d
, 创建但不进入名为my_session的会话, 一般脚本中会这么写Ctrl+b, d
, 脱离当前会话(仍在后台运行);返回Shell界面tmux ls
, 显示会话列表tmux a -t my_session
, 连接指定会话tmux kill-session -t my_session
, 关闭会话my_sessiontmux kill-session -a -t my_session
, 关闭除my_session外的所有会话tmux kill-server
, 关闭所有会话man tmux
, 查看文档- …
下面建一个脚本, 在后台运行ping命令
$ vi test.sh
#!/bin/bash
mysession="test"
# 不管有没有, 先干掉test会话
tmux kill-session -t ${mysession} >> /dev/null
# 新建但不进入test会话
tmux new -s ${mysession} -d
# 向test会话中发送 ping www.baidu.com 命令, 注意要加回车 ENTER
tmux send-keys -t ${mysession} "ping www.baidu.com" ENTER$ chmod 777 test.sh
$ ./test.sh# 列表中发现test会话
$ tmux ls
test: 1 windows (created Thu Jan 6 21:39:00 2022) [80x24]
# 进入test会话
$ tmux a -t test
[detached (from session test)]
发现ping已经运行了起来
# 按 ctrl+b, 然后按d返回shell
# 关闭所有会话
# tmux kill-server
欢迎扫描二维码关注微信公众号, 及时获取最新文章:
这篇关于Shell 基本笔录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!