跳到正文
duanyzhi
返回

SHELL COMMANDS

一份自己攒的 shell 速查。按用途分组,头一栏是分类,进来直接找相应的命令。

目录

一、环境变量与配置

环境变量

让任意目录都能执行某个可执行文件:把它的目录塞进 PATH。

export PATH=/path/to/your/demo:/$PATH

取消环境变量:

unset PATH

~/.bashrc

终端彩色,以及把提示符里的当前路径改成只显示最后一层目录(w 改成 W)。

# 终端彩色
force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
	# We have color support; assume it's compliant with Ecma-48
	# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
	# a case would tend to support setf rather than setaf.)
	color_prompt=yes
    else
	color_prompt=
    fi
fi

# W 表示终端只显示当前目录,把 PS1 这一行的 w 改成 W 就可以了。
if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\W\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\W\$ '
fi
unset color_prompt force_color_prompt

二、网络

连 WiFi

命令行连无线,nmcli 直接一条搞定。改完一般不用重启。

nmcli dev wifi list   # 先扫一下有哪些网
sudo nmcli dev wifi connect "Infinigence-Staff" password "InfiniAI!"

ssh 服务与 scp

sudo apt install openssh-server  # 安装 ssh 服务
service sshd start    # 打开 ssh
service sshd status   # 查看 ssh 状态
service sshd stop     # 关闭 ssh

scp -r file name@ip:/root/            # 拷贝 file 到另一台服务器
scp -P port_id -r file name@ip:/path/ # 带端口号时 -P 必须在 scp 后面

ssh 掉线、终端断连怎么办

连着一会儿就断,看不到最新运行状态,分三层解决。

  1. 改服务端保活配置。
# 服务器修改
vim /etc/ssh/sshd_config
# 把下面几项改大
ClientAliveInterval 60  # 每 60s 自动检查一次,越小越好
ClientAliveCountMax 3
MaxStartups 200
TCPKeepAlive yes

# 重启 ssh
sv restart /opt/devmachine/init/service/sshd
  1. 或者临时登录时带上参数。
ssh -o TCPKeepAlive=yes -o ServerAliveInterval=60 -o ServerAliveCountMax=5 \
  -p 41967 -L 7860:localhost:7860 root@219.135.xxx.xxx
  1. 本地电脑上写成配置,省得每次敲。~/.ssh/config:
Host serve_name
  HostName 219.135.xxx.xxx
  Port 41967
  User root
  TCPKeepAlive yes
  ServerAliveInterval 30
  ServerAliveCountMax 10
  1. 长任务还是丢后台跑,见 六、tmux。

登录别人服务器

把自己机器的公钥贴到对方的 ~/.ssh/authorized_keys 里,之后免密登录。

ssh-keygen -t rsa            # 生成密钥对(已有就跳过)
cat ~/.ssh/id_rsa.pub        # 把这行的内容贴到对方服务器

ftp

root:/workspace   # 在 workspace 目录下登录 ftp
ftp 192.168.1.1   # 登录服务器
# input user name and password
ftp> cd /home
ftp> put file   # 把 workspace 目录下的 file 上传到 ftp 的 /home 目录

wget

wget -q -O a.zip http://www.XXX.zip   # 下载网页文件
# 参数:
-q  # 不显示下载进程
-O  # 定义输出文件名称为 a.zip

三、文件与文本

ls

ls -lh          # 查看文件具体大小,会显示单位 K/M/G
ls -l | wc -l   # 查看文件个数
ls -ltr         # 按照时间顺序排列
ls /path/to/????.jpg  # 列出所有图片前缀是四个字符的文件
ls -d */        # 只列出所有文件夹

find 查找文件

find dir/ -iname *.gcda   # 找到 dir 下所有以 .gcda 结尾的文件
find dir/ \( -iname *.gcda -o -name "*.gcno" \)  # 同时满足两个后缀的文件
find / -name "xxx"        # 从根目录按名字找

locate file.zip  # 查找文件位置(走索引,快)
ack "str"        # 递归查找某个字符,比 grep 顺手

删除符合条件的文件

# 删除当前目录下所有 .abi3.so
find . -name "*.abi3.so" -type f -delete

grep 搜索内容

grep -r "ACLRT_LAUNCH_KERNEL" /usr/local/Ascend/ascend-toolkit

grep -Hrn "abc" --include \*.cpp
# --include 只在 cpp 结尾文件中查找
# -r 递归查找
# -n 输出时带行号
# -i 忽略大小写
# -H 输出文件名

sed 和 cat

sed '/^$/d' old.log > new.log   # 去除 old.log 中所有空行并保存到 new.log
echo "" > log  # 向 log 文件的最后一行添加空行
sed '${/^[[:blank:]]*$/d}' old.log > new.log   # 去除 old.log 最后一行的空行
sed -i 'M,Nd' filename  # 删除文件的 M 到 N 行内容

# sed 替换带 '/' 的字符需要在 / 前面加 \ 转义
sed -i 's/\/usr\/local\/python3.7/\/usr\/python3.7/g' file
sed -i 's/abc.*/aaa/g' file  # 把符合 abc*** 的行全部替换为 aaa

cat -n file        # -n 会显示行号
cat log1 >> log2   # 把 log1 的内容追加到 log2 最后

向某一行插入字符:

sed -i "1i # This is test demo." log  # 向 log 第一行插入字符

查看文件前几行:

cat filename.txt | head -n 10

在每一行增删内容:

sed -e 's/$/abc/' -i file    # 在每行末尾插入 abc
sed -i "s/^/\"/g" file      # 在每行开头插入 "
sed -e "s/$/\"/g" file      # 在每行末尾插入 "
sed -e "/patten str/d" file  # 删除符合条件的行
sed -i "/^#/d" file          # 删除所有以 # 开头的行
sed -i 'N' -e 's/(\n/\(/g' file  # 把 ( 加换行替换成 (

awk

awk '{print $NF}'  // 输出以空格分割最后一个匹配项

awk -F 'name' '{print $2}' file  # 以 name 为分隔符,打印它后面的内容

加了下面这个 log:

  %output.62 : Float(32:5120, 10:512, 512:1) = aten::matmul(%input.121, %2645)
  %outputs.100 : Float(32:5120, 10:512, 512:1) = aten::add_(%output.62, %3527, %2632)
  %x.24 : Float(32:5120, 10:512, 512:1) = aten::add_(%outputs.100, %input.119, %2632)
  %218 : int = prim::Constant[value=1]()
  %2651 : int[] = prim::ListConstruct(%2628)
  %mean.24 : Float(32:10, 10:1, 1:1) = aten::mean(%x.24, %2651, %2629, %2630),
  %2653 : int[] = prim::ListConstruct(%2628)
  %std.24 : Float(32:10, 10:1, 1:1) = aten::std(%x.24, %2653, %2629, %2629),
  %2655 : Float(32:5120, 10:512, 512:1) = aten::sub(%x.24, %mean.24, %2632)
  %2656 : Float(32:5120, 10:512, 512:1) = aten::mul(%3528, %2655)
  %2657 : Float(32:10, 10:1, 1:1) = aten::add(%std.24, %2631, %2632),
  %2658 : Float(32:5120, 10:512, 512:1) = aten::div(%2656, %2657)
  return (%2658)

要拿到所有 aten::** 的算子名:

grep "=" log | sed "/prim::Constant/d" | awk -F " = " '{print $2}' | awk -F "(" '{print $1}'|sort -u
# grep "=" log 把所有含有 = 的行都找出来
# sed "/prim::Constant/d"  删除符合条件的行
# awk -F " = " '{print $2}'  按 = 号切开,取第二段,比如
#  %output.62 : Float(32:5120, 10:512, 512:1) = aten::matmul(%input.121, %2645)
#  输出就是 aten::matmul(%input.121, %2645)
# awk -F "(" '{print $1}'  再按 ( 切开,取第一段
# sort -u  sort 排序,-u 去重

最后结果:

aten::add
aten::add_
aten::div
aten::matmul
aten::mean
aten::mul
aten::std
aten::sub
prim::ListConstruct

head、tail、xargs、tr

head -n 1 File1; tail -n 1 File1  # 选取文件第一行或者最后一行

echo "a b" | xargs mkdir  # 分别创建 a、b 文件夹

tr '\n' ' '  # 用空格替换换行符,即把所有行变成一行
tr -d '"'    # 删除 " 符号

seq 1 10     # 生成 1 到 10 之间的整数

cp、rm、软链接

cp a.so ./    # 直接拷贝 .so
cp -r a.so ./ # 拷贝软链接文件 .so

rm -- --filename   # 文件名带横杠时这样删

拷贝和某个文件同级目录下的所有文件:

file=/path/to/file/abc.so
cp ${file%/*}/* dir/to/path

rsync

rsync -av raw/ des/  # 把 raw 文件夹下面的内容拷贝到 des 目录下

# 假如目录如下
bin/
├── ext
│   ├── remove
│   │   └── empty.txt
│   └── test.cpp
└── torch
    ├── test.gcda
    └── test.gcno
# 将 bin 目录下内容拷贝到 dir 目录下,同时不拷贝 remove 目录下内容
rsync -avAX --exclude=*/remove/\* bin/ dir/

tar、dpkg、rpm

tar -cf md.tar.gz md/  # 压缩 md
tar -xvf md.tar.gz
# 参数:
-v  # 显示进程

dpkg -i pack.deb      # 安装 deb 包
dpkg --remove pack
dpkg -X pack.deb test # 把 deb 文件解压到 test 文件夹
dpkg -L pack_name     # 查看安装包位置

rpm2cpio name.rpm | cpio -i --make-directories  # 解压 rpm 文件
sh pkg.run -list      # 查看 .run 文件
rpm -e packagename    # 卸载 rpm 安装包

四、磁盘与内存

看磁盘大小

df -h /                          # 看根分区还剩多少

du -ah / | sort -hr | head -30   # 找出最占地方的目录 / 文件
du -ah --max-depth=1             # 看当前目录下每个文件、文件夹占多少
du -sh                           # 只显示总占用,比上面快

看内存和 buff/cache

free 里 free 小不代表不够用,主要看 available。buff/cache 是系统拿来缓存磁盘的,随时能回收,一般不用担心。

free -h

# free -h
               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       993Mi       190Mi        67Mi       2.6Gi       2.7Gi
Swap:             0B          0B          0B

真觉得 cache 占得难受,可以手动清(正常没必要):

sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'

清 cache 和孤儿包

sudo apt-get autoclean   # 清理旧版本的软件缓存
sudo apt-get clean       # 清理所有软件缓存
sudo apt-get autoremove  # 删除系统不再使用的孤立软件

清旧内核

dpkg --get-selections | grep linux-image  # 查看已安装内核
uname -a  # 查看电脑当前用的内核
# 删除没用内核:
sudo apt-get remove linux-image-4.13.0-37-generic
sudo apt-get purge linux-image-extra-4.13.0-37-generic
sudo apt-get autoremove linux-image-extra-4.13.0-37-generic
sudo dpkg -r linux-image-extra-4.13.0-38-generic

服务器切到纯命令行

机器不用图形界面时,切到多用户模式,省内存。

sudo systemctl set-default multi-user.target
sudo reboot

五、进程

看进程和占用排行

ps aux --sort=-%mem | head -n 20   # 按内存占用排序,看谁最吃内存
ps aux
ps -eLf          # 查看所有隐藏进程(含线程)
ps -eLf | wc -l  # wc -l 统计行数,也就是进程数
ulimit -u        # 查看系统进程上限

cat /proc/meminfo | head -n 20   # 查看内存详细分布

ps -aux | grep python   # 找到 python 的进程

kill 进程

kill -9 PID
pgrep -f python | xargs kill -9   # 按命令行关键字批量 kill

ulimit 限制资源

给跑起来的程序套个上限,防止把机器吃干。软限制只对当前 shell 和它启动的进程生效。

ulimit -v 30000000   # 限制虚拟内存 30GB(单位 KB)
ulimit -a            # 看看当前所有限制

shell 多线程

用 & 丢后台加 wait 等全部结束。

cmd_list="ls "
cmd_a="python test.py"
cmd_b="python test.py"
cmd_list="${cmd_list} & eval ${cmd_a} & eval ${cmd_b}"
eval ${cmd_list}
wait

六、后台常驻与定时任务

tmux

apt-get install tmux
tmux  # 输入 tmux 进入

# 所有 tmux 命令在输入前都要先按键盘上 ctrl+b,之后命令才生效。
# 按了之后屏幕上没变化,然后输入:
"   # 将 terminal 上下分频
%   # 将 terminal 左右分频
;   # 切换到上一个窗口
o   # 切换到下一个窗口
{   # 当前窗口和上一个窗口交换位置
}   # 当前窗口和下一个窗口交换位置
q   # 显示窗口编号

# tmux 启动鼠标
# ctrl+B,然后输入 : 进入命令行模式,再输入 : set -g mouse on
# 或者把上面这句写到 ~/.tmux.conf 文件中

# tmux 粘贴和赋值都可以按住 shift 来执行

# 同时按下 ctrl+b+o 交换两个窗口位置

tmux attach:断连后找回现场

terminal 断了、也看不了日志,直接重新 attach 上去就行。进去就是最新的运行状态,还能继续交互。

tmux ls   # 查看有哪些后台运行的 tmux

# 1: 1 windows (created Wed Jun 10 20:12:23 2026) (attached)

tmux attach -t 1   # 登陆这个 tmux,恢复现场

at / crontab 定时任务

at:某个时间点跑一次。

date   # 查看时间
echo "hello world" > log | at 20:10   # 在今天 20:10 向 log 文件写入 hello world

crontab:周期性跑。

apt-get install cron
crontab -e  # 打开 crontab
30 10 * * * /path/to/run.sh   # 每天 10:30 跑 run.sh
sudo /etc/init.d/cron start   # 开始运行 cron
sudo /etc/init.d/cron stop    # 停止运行

七、权限

拿 root 权限

ctrl+alt+F2   # 进入超级终端
ctrl+alt+F7   # 退出超级终端

chmod -R 777 directory/   # 给目录加读写执行权限
sudo su                   # 切超级用户,谨慎

改文件属主

把某个目录还给当前用户(比如被 root 建过之后各种写不进去):

sudo chown -R $USER:$USER /path/to/project

八、系统信息

看机器配置

lsb_release -a
uname -a    # 查看是 x86_64(64 位)还是 i686(32 位)
cat /etc/*-release
cat /proc/cpuinfo
cat /proc/driver/nvidia/version  # 驱动版本号
cat /proc/meminfo                # 查看内存
free -m                          # 以 MB 为单位查看 ram 大小

看 .so 文件

nm -D *.so   # 查看 .so 中定义的 symbol,列出所有动态链接符号

# strip 去掉符号表,版本发布时一般不能暴露符号表,需要去除:
strip libname.so
nm libname.so   # 会显示 no symbols,说明符号已经没了

readelf -V *.so | grep name      # 从 .so 中读取出筛选内容
readelf -D *.so | grep "R.*PATH" # 查看 so 库设置的 rpath,rpath 优先级大于 LD_LIBRARY_PATH

九、写 shell 脚本

.sh 常用写法

$1       # 运行 .sh 时的输入参数
set -e   # 一般放 .sh 最上面,某个命令返回 error 就终止脚本

pushd $DIR  # 进去 DIR 目录
popd        # 退出目录

新建一个字符串列表:

MY_LIST=(
python
cpp
)

for str in "${MY_LIST[@]}"; do
  echo $str
done

NEW_LIST=(${MY_LIST[*]})   # 把 MY_LIST 赋值给另一个变量

echo "num of MY_LIST" ${#MY_LIST[*]}   # 输出 MY_LIST 元素个数

判断文件夹 / 文件是否存在:

if [ -d dir ]; then
   echo "dir is exist"
fi

if [ -f file ]; then
   echo "file is exist"
fi

切分字符串:

str=path/to/name
dir="$(cut -d'/' -f1 <<< "$str")"   # 按 / 切分并取出 f1,第一个字段
echo $dir
# path

赋值、自增:

num=1
num=$((num+1))   # num+1 并重新赋值给 num

逐行读文件:

while IFS= read -r line || [ -n "$line" ]; do
  echo $line   # 把每一行打印出来
done < log     # 读取 log 文件中每一行

加函数:

FUN() {
echo "do something"
}

FUN   # 运行函数

正则在 shell 里的用法:

# log 文件内容如下
echo "This is log file"
dense=<"0xB5508">

# 用正则把 dense=<"0xB5508"> 替换掉
sed -i "s/dense<\"0\([xX]\)\([0-9a-fA-F]*\)\"/dense<\"{{0[xX][0-9a-fA-F]+}}\"/g" log

给脚本传参

方法一

# script.sh
usage(){
    echo "Usage of install.sh"
    echo "-p  set param"
    echo "-h  print usage"
}

PARAM=""

while getopts "p:h:" opt
do
  echo "all parameters: "$opt
  case $opt in
    p)
    PARAM=$OPTARG;;    # 把参数值给 PARAM 变量
    h)
    usage
    exit 0;;
    ?)
	echo "there is unrecognized parameter."
	exit 1;;
  esac
done

# 使用用法:
sh script.sh -p true

# 这种方式传参 -p 后面必须要加参数内容

方法二

# script.sh
PARAM=""

while [[ $# -gt 0 ]]; do
  key="$1"

  case $key in
    -p|--performance)
      PARAM="true"
      shift
      shift;;
    -h|--help)
      exit 0;;
    *)
      echo "unknown option."
      shift;;
  esac
done

# 使用方法:
sh script.sh -p

# 这种方法传参数 -p 后面不需要跟内容

输出所有传入的命令行参数:

#!/bin/bash
echo ${@:2}   # 输出所有的命令行参数

# a.sh 1 2 3 4
# out: 1 2 3 4

给函数传参

fun(){
  arg1=$1  # 这里的 $1 获取的不是 shell 脚本的输入,而是函数 fun 的输入
  echo "arg1:"$arg1
}

fun aaa  # 把 aaa 以参数形式送给函数 fun

模拟字典

info_list=(
  "name time"
)

for info in "${info_list[@]}"; do
    info_dict=($info)
    name=${net_dict[0]}
    time=${net_dict[1]}
done

eval

cmd="ls | grep aaa"
eval $cmd   # 执行 cmd 所表示的语句

脚本开头 /bin/bash

#!/bin/bash
# 一般在 script 文件开头加上这一句。目的是统一脚本在不同系统下运行的环境,
# 保证各个系统都用 /bin/bash 跑这个脚本,因为有些系统默认 bash 不是 /bin/bash,
# 会导致运行脚本出错。

生成随机数

echo $(((RANDOM % 10) + 1))   # 生成 1 到 10 之间的随机数

十、杂项

shortcut

ctrl+H          # 查看隐藏文件
df              # 查看 boost 分区空间
ifconfig        # 查看 ip
Ctrl+shift++    # 增加字体,ctrl+- 减小字体
history         # 查看历史 terminal 命令
windows+1/2/3   # 切换不同左侧锁定的应用
ctrl+windows+D  # 显示桌面
alt+tab         # 前后两个应用之间切换 / 可以作为双屏之间切换
# 左侧工具栏可以隐藏

windows 和 ubuntu 时间不一样

sudo apt-get install ntpdate
sudo ntpdate time.windows.com
sudo hwclock --localtime --systohc

ubuntu 解决 home 空间不足

1. windows 下下载 [Gparted](https://sourceforge.net/projects/gparted/files/gparted-live-testing/OldFiles/)
2. 制作 U 盘启动工具:
   打开 UltraISO 工具 - 文件 -> 打开(下载的镜像)> 启动 -> 写入硬盘映像 -> 选择 U 盘驱动器 -> 格式化 -> 写入
3. 我的电脑右键管理 - 磁盘管理 - 点击一个有空余的磁盘 - 压缩卷 - 压缩出一部分空余未分配磁盘空间。
4. 重启 - U 盘启动:
   进入 Gparted 界面 -> Default settings - Don't touch keymap -> 选择语言 -> 输入 26(简体中文)-> 输入 0 进入 X-Windows
5. 弹出 Gparted 磁盘界面,显示自己的磁盘分布 -> 选择 home 分区所在的分区:/ -> 右键点击 Resize/Move -> 点击拖动上方内存条
   使得 New Size 最大,即把未分配的空间分配到 home 下。
6. 点击 Resize/Move -> Apply
7. 重启即可

yum

yum install -y XXXX   # -y 表示安装过程中让选 yes/no 时默认选 yes

hollywood

sudo apt-get install hollywood
cmatrix
hollywood
sudo apt-get install oneko
oneko

分享这篇文章:

上一篇
ResNet
下一篇
C++ Basics