Linux Shell 实践

快捷键

  • Ctrl+r 快速查找历史命令
  • Ctrl+l 清理控制台屏幕

移动光标

  • Ctrl+a 移动光标到行首
  • Ctrl+e 移动光标到行尾
  • Alt+Left Arrow 移动光标到上一个单词
  • Alt+Right Arrow 移动光标到下一个单词

删除字符

  • Ctrl+u 删除光标之前的内容
  • Ctrl+k 删除光标之后的内容
  • Ctrl+w 删除光标前面的一个单词

进程

  • Ctrl+d 退出。等同于exit命令
  • Ctrl+z 当前运行的程序后台运行。如果一步到位,可以在命令后面加 &

重定向

  • 执行时的错误信息输出到文件(2>)
hello 2> log.error
$ cat log.error 
-bash: hello: 未找到命令
  • 执行时的所有信息都输出到文件(&>)
echo hello &> log.info
$ cat log.info 
hello
  • 创建一个文件并写入内容(> filename <<EOF)
cat > hello.sh << EOF
#!/bin/bash
echo hello
EOF

变量

变量赋值

  • 执行结果保存到变量($() ``)
var1=$(pwd)
var2=`pwd`
  • 整数四则运算(let)
let n=10-3+4/2
echo $n
9

变量引用 ${var} 大部分情况可省略为

Linux Shell 执行方式

在当前shell下一行执行多条命令(;)

cd /etc/ssh ; cat ssh_config ; pwd ; du -sh /etc/ssh/ssh_config

创建shell脚本

vim ssh_config-info.sh
#!/bin/bash
cd /etc/ssh
cat ssh_config
pwd
du -sh /etc/ssh/ssh_config

shell脚本执行方式

bash ssh_config-info.sh

  • 创建子进程执行脚本
bash ssh_config-info.sh
$ pwd
/root

./ssh_config-info.sh

  • 需要执行权限
chmod u+x ssh_config-info.sh
  • 使用脚本文件中第一行#!指定的shell创建子进程执行脚本
./ssh_config-info.sh
$ pwd
/root

source ssh_config-info.sh

  • 在当前shell进程中执行,会对当前shell产生影响
source ssh_config-info.sh
$ pwd
/etc/ssh

. ssh_config-info.sh

  • 在当前shell进程中执行,会对当前shell产生影响(.相当于source)
. ssh_config-info.sh
$ pwd
/etc/ssh

抽取视频关键帧保存zip文件

抽取视频的关键帧,保存为zip文件。

目录结构

.
├── keyframes
│   ├── race
│   │   ├── race-0001.jpg
│   │   ├── race-0002.jpg
│   │   └── race-0096.jpg
│   └── race.zip
└── videos
    └── race.mp4

自动化脚本 _prompt='██' #find返回的文件列表在macOS系统上不能使用for循环进行迭代。 video_files=$(find videos -type f \ -iname '.mov' -o \ -iname '.mts' -o \ -iname '.mp4' -o \ -iname '.mkv' -o \ -iname '.webm' -o \ -iname '.flv' -o \ -iname '.f4v' -o \ -iname '.vob' -o \ -iname '.ogg' -o \ -iname '.ogv' -o \ -iname '.avi' -o \ -iname '.

命令tar

    -c, --create Create a new archive.  Arguments supply the names of the files to be archived.
    -x, --extract, --get Extract files from an archive.
    -z, --gzip, --gunzip, --ungzip Filter the archive through gzip(1).
    -j, --bzip2 Filter the archive through bzip2(1).
    -f, --file=ARCHIVE Use archive file or device ARCHIVE.  If this option is not given, tar will first examine the environment variable `TAPE'.  If it is set, its value will be used as the archive  name.   Otherwise, tar will assume the compiled-in default.
    -t, --list List the contents of an archive.
    -v, --verbose Verbosely list files processed.

命令zip

准备 yolov5

yolov5/
├── detect.py
├── Dockerfile
├── hubconf.py
├── LICENSE
├── models
│   ├── common.py
│   ├── experimental.py
│   ├── export.py
│   ├── __init__.py
│   ├── yolo.py
│   ├── yolov5l.yaml
│   ├── yolov5m.yaml
│   ├── yolov5s.yaml
│   └── yolov5x.yaml
├── README.md
├── requirements.txt
├── test.py
├── train.py
├── tutorial.ipynb
└── weights
    └── download_weights.sh

打包整个目录

zip -r yolov5.zip yolov5/

排除目录和文件

打包前,最好把之前的 zip 文件删除,不然是增量追加,还会看到排除的目录和文件。

zip -r yolov5.zip yolov5/ -x "yolov5/.git/*" -x "yolov5/.github/*" -x "yolov5/.gitattributes"

排除所有的 yaml 文件 zip -r yolov5.

命令cp

拷贝一批文本文件(10000)到目录

cp

  • time: 0.470s
  • 当文件更新了或者缺少时才拷贝。(-u)
  • 速度最快
cp -u labels/*/*.txt datasets/yolo/sign/labels/

xargs

  • time: 30.003s
ls labels/*/*.txt | xargs -I {} cp {} datasets/yolo/sign/labels/

find -exec

  • time: 32.521s
find labels/ -type f -iname '*.txt' -exec cp {} datasets/yolo/sign/labels/ \;

for

  • time: 41.259s
for i in `ls labels/*/*.txt`; do cp $i datasets/yolo/sign/labels/; done

参考资料

命令du

du - 估计文件空间使用量

    -s, --summarize display only a total for each argument
    -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)

查看当前文件夹所有文件占用的空间

du -sh
15G	.

查看当前文件夹下的一级目录和文件占用的空间

du -sh *
14G	ailab
178M	software
4.0K	test.txt
33M	tmp

命令top

快捷键

  • Shift+p 按CPU使用率排序
  • Shift+m 按内存使用率排序
  • 1 显示每个逻辑CPU的状态

查看指定进程

top -p $pid
  • 查看1号进行
top -p 1
top -p1
top - 22:58:02 up 323 days, 12:09,  2 users,  load average: 0.64, 0.61, 0.38
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  7.2 us,  1.8 sy,  0.0 ni, 90.3 id,  0.0 wa,  0.5 hi,  0.2 si,  0.0 st
MiB Mem :   3780.8 total,    400.2 free,   1749.6 used,   1631.0 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   1939.3 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
    1 root      20   0  178540   7680   3792 S   0.0   0.2   7:50.54 systemd

vim实践

安装

版本

  • vim
  • vim-gtk (KDE)
  • vim-gtk3 (GNOME)
  • vim-tiny (最小功能)

查看安装的 vim 版本

apt list --installed | grep vim
yum list installed | grep vim

安装带图形界面的版本

macOS MacVim

Ubuntu

sudo apt install vim-gtk3

运行

vim -g
gvim

查看可用插件

  • vim --version
  • 打开 vim,输入命令 :version

四种模式

  • 正常模式
  • 插入模式
    • 进入方式
      • i 光标当前位置进入
      • Shift+i 光标所在行的开头位置进入
      • a 光标当前位置下一个字符进入
      • Shift+a 光标所在行的行尾位置进入
      • o 光标所在行下插入空行
      • Shift+o 光标所在行上插入空行
    • 退出
      • 按esc键
  • 命令模式
    • 进入方式
      • : 设置命令
      • / 向下搜索
      • ? 向上搜索
    • 退出
      • 按两次esc键
  • 可视模式
    • 进入方式
      • v 字符
      • Shift+v
      • Ctrl+v
    • 操作
      • d 删除选择
      • y 复制
      • Shift+i 块插入 (输入插入字符后,按两次esc键。)
    • 退出
      • 按两次esc键

文件

  • :q 没有修改直接退出
  • :q! 放弃修改退出
  • :w 保存
  • :wq 保存退出
    • :wq filename 保存退出
  • ZZ 保存退出
  • :!command 运行shell命令
    • :!ls -l 查看当前目录列表
    • :!ifconfig 查看本地IP地址

命令ln

在文件之间建立链接

    ln [OPTION]... [-T] TARGET LINK_NAME
    ln [OPTION]... TARGET
    ln [OPTION]... TARGET... DIRECTORY
    ln [OPTION]... -t DIRECTORY TARGET...

文件或目录的软链接(类似指针)

创建

ln -s /data/apt-mirror/mirror/archive.ubuntu.com/ubuntu /var/www/ubuntu

查看

$ ll /var/www/ubuntu
lrwxrwxrwx 1 root root 49 Jan 15 00:23 /var/www/ubuntu -> /data/apt-mirror/mirror/archive.ubuntu.com/ubuntu/

删除

  1. unlink
unlink /var/www/ubuntu
  1. rm
rm /var/www/ubuntu

参考资料

命令chown

更改文件所有者和组

    chown [OPTION]... [OWNER][:[GROUP]] FILE...

修改文件或目录的所有者

sudo chown root filename
-rw-rw-r-- 1 root wjj    0 Jan 15 02:35 filename

修改文件或目录的组

sudo chown :root filename
-rw-rw-r-- 1 root root    0 Jan 15 02:35 filename

修改文件或目录的所有者和组

sudo chown wjj:wjj filename
-rw-rw-r-- 1 wjj:wjj    0 Jan 15 02:35 filename

修改目录下所有文件和目录的所有者和组

sudo chown -R root:root test

参考资料

基于Apt-Mirror创建私有Ubuntu存储库

服务端

apt-mirror下载软件包

  1. 安装apt-mirror
sudo apt-get install apt-mirror -y
#修复FAQ1
sudo curl -fsSL https://raw.githubusercontent.com/Stifler6996/apt-mirror/master/apt-mirror > apt-mirror

配置mirror.list sudo nano /etc/apt/mirror.list ############# config ################## set base_path /data/apt-mirror #set mirror_path $base_path/mirror #set skel_path $base_path/skel #set var_path $base_path/var #set cleanscript $var_path/clean.sh #set defaultarch <running host architecture> #set postmirror_script $var_path/postmirror.

基于PyPIServer创建私有Python软件包存储库

服务端

拉取PyPIServer镜像

docker pull pypiserver/pypiserver:latest

部署PyPIServer

  • 只用于客户端下载(用作缓存加速)
docker run -d --restart=always --name pypiserver -p 8080:8080 \
    -v /data/pypi-packages/:/data/packages \
    pypiserver/pypiserver:latest
  • 客户端不仅可以下载还可以上传(当我们自己开发了Python的软件时)
#创建用户名和密码
sudo apt install apache2-utils -y
sudo mkdir /data/pypi-packages
sudo htpasswd -sc /data/pypi-packages/htpasswd.txt wjj
#当您需要再创建用户名时就不需要加参数 -c
sudo htpasswd -s /data/pypi-packages/htpasswd.txt test
#容器部署
docker run -d --restart=always --name pypiserver -p 8080:8080 \
    -v /data/pypi-packages/:/data/packages \
    pypiserver/pypiserver:latest -P /data/packages/htpasswd.txt

Docker实践

安装与卸载

安装

  • 快速安装
curl -fsSL https://get.docker.com | sh -

卸载

  • apt
apt-get remove --auto-remove docker
  • yum
yum remove docker docker-common docker-selinux docker-engine

指定显卡(NVIDIA_VISIBLE_DEVICES)

#指定单张GPU卡
docker run --runtime=nvidia -d -e NVIDIA_VISIBLE_DEVICES=0 gouchicao/yolov5:train
#指定多张GPU卡,多个逗号隔开。
docker run --runtime=nvidia -d -e NVIDIA_VISIBLE_DEVICES=0,1 gouchicao/yolov5:train
#NVIDIA_VISIBLE_DEVICES默认值是all
docker run --runtime=nvidia -d gouchicao/yolov5:train

重启策略 方法 启动容器时通过参数指定 #如果容器停止总是重新启动。如果手动停止,则仅在Docker守护程序重启或手动重启容器本身时才重启。

Apache HTTP Server实践

修改端口号

  • /etc/apache2/ports.conf
sudo nano /etc/apache2/ports.conf
# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf

Listen 8081
......
......
  • /etc/apache2/sites-enabled/000-default.conf
sudo nano /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:8081>
......
......
</VirtualHost>
  • 重启服务
sudo systemctl restart apache2

参考资料

Dockerfile OpenCV4 Ubuntu20.04

Dockerfile

FROM ubuntu:20.04
LABEL maintainer="wang-junjian@qq.com"

#auto install tzdata(opencv depend)
ENV DEBIAN_FRONTEND=noninteractive

RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get update && apt-get install -y \
    python3 python3-pip \
    libglib2.0-dev libgl1-mesa-glx \
    && rm -rf /var/lib/apt/lists/*

RUN ln -s /usr/bin/python3 /usr/bin/python && \
    ln -s /usr/bin/pip3 /usr/bin/pip
RUN pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ \
    opencv-python opencv-contrib-python

#set your localtime
RUN ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

WORKDIR /

CMD bash

Building ONNX Runtime

NVIDIA CUDA

单步构建

  • 下载onnxruntime源代码
git clone --recursive https://github.com/microsoft/onnxruntime.git
  • 拉取容器(编译环境)
docker pull nvidia/cuda:11.1-cudnn8-devel-ubuntu20.04
  • 运行容器
docker run -it --name build-onnxruntime-gpu --runtime nvidia \
    -v $(pwd)/onnxruntime:/onnxruntime -w /onnxruntime \
    nvidia/cuda:11.1-cudnn8-devel-ubuntu20.04
  • 更新apt镜像源
sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
apt-get update
  • 安装依赖包
apt-get install language-pack-en git cmake python3 python3-pip -y
  • 修改语言环境
locale-gen en_US.UTF-8
update-locale LANG=en_US.UTF-8
  • 更新pip镜像源
pip3 config set global.index-url https://mirrors.aliyun.com/pypi/simple/

Dockerfile ONNXRuntime GPU

FROM nvidia/cuda:11.1-cudnn8-devel-ubuntu20.04 AS builder
LABEL maintainer="wang-junjian@qq.com"

#E: Failed to fetch https://developer.download.nvidia.cn/compute/cuda/repos/ubuntu2004/x86_64/by-hash/SHA256/f10fc2a7a0d072ddcf141af2ef28f1e97ab4b3a5c3b9bbe34ed845d174fb4979  404  Not Found [IP: 61.155.167.2 443]
#E: Some index files failed to download. They have been ignored, or old ones used instead.
RUN rm /etc/apt/sources.list.d/cuda.list /etc/apt/sources.list.d/nvidia-ml.list

RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
    apt-get update && \
    apt-get install language-pack-en git python3 python3-pip -y && \
    DEBIAN_FRONTEND=noninteractive apt-get install cmake -y && \
    locale-gen en_US.UTF-8 && \
    update-locale LANG=en_US.UTF-8

RUN pip3 install numpy -i https://mirrors.aliyun.com/pypi/simple/
// ...

VLC Extension Example

开发

编写脚本 hello.lua

function descriptor()
    return {
        title = "Hello World";
        version = "1.0";
        author = "WangJunjian";
        url = 'www.wangjunjian.com';
        shortdesc = "Hello World";
        description = "Hello World!";
        capabilities = {"menu"}
    }
end

-- activate() : called when the extension is activated from within VLC
function activate()
    create_dialog()
end

-- deactivate() : called when the extension is deactivated from within VLC
function deactivate()
    close()
    vlc.deactivate()
end

-- create_dialog() : creates the dialog containing the initial widgets
function create_dialog()
    dlg = vlc.dialog(descriptor().title)
    dlg:add_label("<b>Hello World: VLC Lua scripts and extensions</b>")
end

命令ffmpeg

FFmpeg

  • 格式转换 -y(覆盖输出文件)
ffmpeg -y -i input.mp4 output.avi
  • 生成gif(低质量) -pix_fmt(像素格式) -s(设置帧大小WxH)
ffmpeg -y -i input.mp4 -pix_fmt rgb8 -r 10 -s 320x240 output.gif
ffmpeg -y -i input.mp4 -pix_fmt rgb8 -r 10 -vf 'scale=320:-1' output.gif
  • 生成gif(高质量) -ss(开始时间偏移) -t(持续时间)
ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 output.gif
ffmpeg -y -ss 5 -t 5 -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 output.gif
  • 每秒抽取一张图片 -r(设置帧速率)
ffmpeg -i input.mp4 -r 1 -s 1024x768 -f image2 input-%03d.jpeg

命令history

操作不记录在历史记录中

有选择性地进行记录(操作命令前面加空格就不记录)

  • 当前会话临时生效
HISTCONTROL=ignorespace
  • 持久化设置,可以修改配置文件:.bash_profile 或 .bashrc。执行source命令后,设置生效。你也可以退出后重新登录。
$ nano .bashrc
export HISTCONTROL=ignorespace
$ source .bashrc

所有的操作不记录

HISTSIZE=0

只在当前会话中起作用,要想持久化请参考上面的设置。

删除历史记录中的某行

history -d linenumber

清除历史记录

history -c

参考资料

在YOLOv5中运行JupyterLab和TensorBoard

构建可用的JupyterLab和TensorBoard

  • 启动YOLOv5容器
docker run --ipc=host --runtime nvidia -it -p 8888:8888 \
    -v ${dataset_dir}:/usr/src/app/project \
    ultralytics/yolov5:latest
  • 安装版本1的TensorBoard。(解决FAQ1的问题:jupyter-tensorboard 0.2.0不支持高于TensorBoard 2.0的版本。YOLOv5镜像中安装的TensorBoard 2.4的版本。)
pip uninstall tensorboard -y && pip install tensorboard==1.15
  • 运行JupyterLab
jupyter lab --no-browser --ip 0.0.0.0 --port 8888
  • 本地浏览器进行访问
http://ip:8888/lab

FAQ Launcher Error - Invalid response: 500 Internal Server Error Uncaught exception POST /api/tensorboard?1609481325314 (192.168.1.