整理一下關於 Linux 上 CV 開發環境的各種工具的配置。包括各種錯誤的處理,在無 root 權限下安裝到指定目錄,以及多人共用 root 帳戶的情況下重複安裝不同版本且不影響系統中已存在的版本。

從幾個文件目錄開始

bin 放置可執行的二進制程序,可以直接運行;lib 是一些動態鏈接庫,其它程序依賴;include 則是一些 C 的頭文件,在編譯程序的時候,要 include 進來。

/bin:zsh、ls、rm、mkdir,所有用戶可以使用的與系統相關的程序。/sbin:shutdown、ifconfig、mount,系統運行直接相關的需要 root 權限的程序
/usr/bin:whereis、tar、clang、g++,系統預裝的程序。/usr/sbin 同樣為需要 root 權限的
/usr/local/bin:ffmpeg、x264,一些自己安裝的第三方程序。/usr/local/sbin 同理

此外一些包管理軟件,例如 Homebrew 安裝在 /usr/local/Cellar/ 下,並軟鏈接到 /usr/local/bin。一些大型的包管理軟件比如 Anaconda 會安裝在 /usr/local/opt~/opt 下。

環境変量

上述這些 bin 文件夾都是默認在 PATH 中的,所以打開 Terminal 直接敲指令就可以使用,不需要帶程序路徑,如果在其它地方的程序,就需要軟鏈接到這裡(/usr/local/bin),或者把其它路徑加到 PATH 中,例如 ~/.bashrc/~/.zshrcexport PATH=/Users/kotori/opt/anaconda3/bin:$PATH

同樣的,在上述標準的動態鏈接庫 lib 內的 .so 也可以正常被其它需要調用的程序識別到,也可以軟鏈接(到 /usr/local/lib)或 export LD_LIBRARY_PATH=/mnt/x264-master:$LD_LIBRARY_PATH。查看已在環境中的 lib 的位置 ldconfig -p | grep lib

如果 head file 不在上述標準的 include 文件夾内,那麽 gcc 編譯的時候就要指定一下 -I

例如在 macOS 用 Homebrew 時,如果檢測到系統已經安裝了某程序,那麼它就不會把 /usr/local/Cellar/ 內的程序鏈接到 /usr/local/binbrew info opencv@3 顯示:

1
2
opencv@3 is keg-only, which means it was not symlinked into /usr/local, because this is an alternate version of another formula.
/usr/local/Cellar/opencv@3/3.4.5_6 (656 files, 235.6MB)

這時候如果其它程序編譯需要 Homebrew 的這個版本的 OpenCV 而不是系統内原有的話,就要指定一下 -I/usr/local/Cellar/opencv@3/3.4.5_6/include-L/usr/local/Cellar/opencv@3/3.4.5_6/lib

多版本共存

一般軟件編譯后的 sudo make install 就是直接將編譯得到的可執行文件和 lib 複製到 usr/local。如果無 root 權限,或是多人共用 root 而系統内已經有一個別人裝好的,但這個版本/配置不符合要求時,可以不進行 sudo make install,而是統一在:

在有自己賬戶時,可以在 bashrc 中配置 export XXX,這樣每次登錄時自動把自定義目錄添加到環境變量中。

多人共用 root 時,可以在 bashrc 中配置一個 alias XXX=export XXX,每次登錄 shell 時敲一下,不影響其他人。

Conda

conda 不僅可以管理 Python 包(安裝在 miniconda3/envs/<env_name>/lib/python3.x/site-packages),也可以管理其他軟件(bin/lib,例如 Cuda/FFmpeg 等)(安裝在 miniconda3/envs/<env_name>/bin)。

SSH

ssh-keygen -t rsa -C "<comment>" 生成公鑰私鑰,ssh-copy-id -i ~/.ssh/id_rsa.pub root@10.x.x.x 將 public key 寫入到遠程機器的 ~/.ssh/authorized_key 文件中,或者(通過其它接口)手動複製進去。

Cuda

要安裝以下幾個東西,除了驅動以外其它不如找個 PyTorch 官方 Docker 鏡像直接解決,在宿主機折騰還容易出問題,Driver 在服務器上一般也沒法自己裝:

  • 顯卡驅動,也就是 nvidia-smi 會顯示的版本。

https://www.nvidia.com/download/Find.aspx 按 Cuda ToolKit 版本搜索最新,一個 .run 文件(.run 前面一半是個安裝 shell 指令,後面一半是個安裝文件 tar)。

  • cuda complier/cuda runtime toolkit

也就是 nvcc -V 會顯示的版本,準確說顯示的是 Runtime API 的版本。我見過 Driver API Version: 9.2, Runtime API Version: 9.0 的機器,一般要求的都是 Runtime API 版本,它是 Driver API 的更高一層抽象,基本全部都是調用的 Runtime API。想要不坑最好還是把 Cuda 更新到很新,在 2020 就是 10.2(目前 11.x 已經發布),可以看一下 PyTorch 它提供的編譯好的版本中 Cuda 最新的是哪個即可。

在 conda 環境中可以直接 conda install cudatoolkit=10.2。在外面的話 https://developer.nvidia.com/cuda-downloads 在 Legacy Releases 中,有 run/deb/rpm 包,我喜歡用 run 的。

  • cudnn,用於深度學習的加速庫 (CUDA Deep Neural Network library),cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2 可查看版本。

https://developer.nvidia.com/cudnn 要註冊,填一個 survey。有 tar/deb/rpm,它是一個編譯好了的 lib 和一些 head,我喜歡用 tar 然後 cp && chomod 即可。參考 installlinux-tar。下載時選第一個 cuDNN Library for Linux (x86) 即可,如果得到 solitairetheme8 後綴的文件手動改一下後綴名即可。

  • 如果有多卡,還需要 nccl,一個多卡之間的通信後端(比如 PyTorch 中的 torch.distributed 中很多方法就是 nccl 的實現)

https://developer.nvidia.com/nccl/nccl-download 同樣要註冊和填一個 survey。只有 Ubuntu/Debian 的 deb 和 RedHat/CentOS 的 rpm,按對應系統選即可。

由於 Cuda 和 前面的 CPU 工具是並行的存在,所以這些 GPU 相關東西都會裝在 /usr/local/cuda 中,調用 Cuda 的軟件也會自動在這個目錄下查找 bin 和 lib 和 include。在 Windows 下的 cuda 文件夾會自動帶上版本號,因此可以多版本共存。在 Linux 下,Cuda 10.1 update2 之後可以指定安裝目錄。

FFmpeg with nvenc

前幾個月聽說現在 NVENC 效果不錯了,配置了一個試試看,大概 6x 的速度,1.4x 的文件體積?對於不極致質量追求的地方應該說相當好用。官網:developer.nvidia.comtrac.ffmpeg.org/wiki/HWAccelIntro

用包管理器的好處就是它真的很貼心,常用的組件通通給配好了。自己編譯的話,每個依賴都要先手動裝好然後在 configure 裡 enable。但是目前包管理器安裝的 FFmpeg 一般都不會帶 GPU 編碼器。

系統環境

driver 版本 Driver Version: 396.44
complier/cuda toolkit 版本 Cuda compilation tools, release 9.0, V9.0.176

這裡有個坑點,nvenc API version 並不知道怎麼查看,而它直接關係到頭文件的版本,我隨便編譯了一個之後運行的時候顯示,這裡才看到是 8.1

1
2
[h264_nvenc @ 0x36d8640] Driver does not support the required nvenc API version. Required: 10.0 Found: 8.1
[h264_nvenc @ 0x36d8640] The minimum required Nvidia driver for nvenc is 445.87 or newer

然後重新搞了一個,反正也挺快的。。。

Dependencies

Compiler

除了 gcc/g++ 之外,ffmpeg 为了提高效率使用了汇编指令,如 MMX 和 SSE 等,所以先要安裝 yasm,x264 還需要 nasm,否則會報錯 nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.

yasm:Debian 下直接 sudo apt-get install yasm

nasm:www.nasm.us,下載後直接運行 ./configure,尋找編譯器並生成相應 Makefile,然後 make 編譯,之後 make install 裝進 /usr/local/bin

x264

我怎麼覺得 libavcodec 就帶了 x264 編解碼啊?但是實踐告訴我 Unknown encoder 'libx264' 就是要單獨搞搞。

總還是會用到 CPU 編碼,所以 git clone https://code.videolan.org/videolan/x264.git 得到源碼後,./configure --enable-static --enable-shared,然後 make -> sudo make install 給它編譯安裝。

這會生成 .a (Archive libraries) 靜態編譯的程序會用到,和 .so (shared object) 的動態庫

libmp3lame

一個 mp3 的編碼器,總之 FFmpeg 啥都要自己配好才工作,apt-get install libmp3lame-dev 或者與 x264 一樣的安裝方式。它好像也可以 AAC,我試了下是 OK 的?

Head File

然後 clone 一下頭文件 https://github.com/FFmpeg/nv-codec-headers,這裡知道系統裡的 API 是 8.1 的(上面那個系統環境版本簡直太「經典」了),所以 git checkout -b sdk/8.1 origin/sdk/8.1 把老版本的拉下來。cd nv-codec-headers && sudo make install && cd – 編譯。

Compile and Command

把 FFmpeg clone 下來,然後配置啟動一下 x264、libmp3lame、nvenc,cuda 不在標準目錄要指定一下 -I-L

./configure --enable-cuda-nvcc --enable-cuvid --enable-nvenc --enable-nonfree --enable-libnpp --enable-gpl --enable-libx264 --enable-libmp3lame --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64

生成 Makefile 後,make -j 10 -> make install

我這裡碰到奇怪情況,make install 後好像沒在環境変量裡,x264 也是。運行會顯示:./ffmpeg: error while loading shared libraries: libx264.so.161: cannot open shared object file: No such file or directoryldd ./ffmpeg 看了下,顯示以下:

1
2
3
4
5
6
linux-vdso.so.1 (0x00007fff12dac000)
...
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f52f5bcf000)
libx264.so.161 => not found
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f52f59b2000)
...

/usr/local/lib 裡明明有個 libx264.so soft link -> libx264.so.161,不知道它為啥要找帶版本號後綴的。有說 /etc/ld.so.conf 加上 x264 clone 到的目錄然後 sudo ldconfig。感覺不如直接 export LD_LIBRARY_PATH=/mnt/x264-master:$LD_LIBRARY_PATH,然後把 FFmpeg 也 export 到 PATH 裡。

command

ffmpeg -hwaccel cuvid -hwaccel_output_format cuda (-c:v h264_cuvid) -i a.avi -i b.mp4 -map 0:0 -map 1:1 -c:v h264_nvenc -c:a copy -y c.mp4

啟用 GPU 編解碼,加上解碼也有不小速度提升,source 不是 h.264 的也有提升(去掉括號內的)。

FFmpeg Static Builds

官網上發現有個 static build,不用 GPU 的話不如直接用這玩意方便,什麼都帶。

一鍵安裝腳本

innerlee/setup 這個 repo 提供了常用軟件的安裝腳本。

配置環境變量

1
2
3
export ZZROOT=${some path}/app
export PATH=$ZZROOT/bin:$PATH
export LD_LIBRARY_PATH=$ZZROOT/lib:$ZZROOT/lib64:$LD_LIBRARY_PATH

所有腳本會把 downloads,解壓到 src,然後編譯並安裝到 binlibDCMAKE_INSTALL_PREFIX=$ZZROOT 和其它一系列 FLAGS。

make DESTDIR=/home/john install

TroubleShoot

對於 CMake 中需要下載的一些網絡資源,例如儲存在 GitHub 上,以 OpenCV 為例。

opencv/3rdparty/ippicv 中會下載 ~60 MB 的 ippicv,在 opencv_contrib/modules/xfeatures2d 中會下載 boostdesc_binboost 和 vgg_generated。這些二進制文件都在 opencv_3rdparty repo 不同的 branch 中,可以看一下 .cmake 文件中的 SHA,例如 set(IPPICV_COMMIT "a56b6ac6f030c312b2dce17430eef13aed9af274"),再找到對應的 branch(一般就是最新的,檢查一下 iigalanin Update IPPICV binaries (20191018) a56b6ac on Feb 25)。

1
2
3
4
5
6
7
8
9
set(IPPICV_COMMIT "a56b6ac6f030c312b2dce17430eef13aed9af274")

"${OPENCV_IPPICV_URL}"
"$ENV{OPENCV_IPPICV_URL}"
"https://raw.githubusercontent.com/opencv/opencv_3rdparty/${IPPICV_COMMIT}/ippicv/"

if(X86_64)
set(OPENCV_ICV_NAME "ippicv_2019_lnx_intel64_general_20180723.tgz")
set(OPENCV_ICV_HASH "c0bd78adb4156bbf552c1dfe90599607")

拼接 https://raw.githubusercontent.com/opencv/opencv_3rdparty/32e315a5b106a7b89dbed51c28f8120a48b368b4/ippicv/ippicv_2019_lnx_intel64_general_20180723.tgz

以 ippicv 爲例,牆内一般卡在 IPPICV: Download: ippicv_2019_lnx_intel64_general_20180723.tgz 然後超時。

把這些用代理下載好後,放到例如 $ZZROOT/app/3rdparty 中,然後修改對應 cmake 文件中的

1
2
3
4
5
6
7
8
9
10
ocv_download(FILENAME ${OPENCV_ICV_NAME}
HASH ${OPENCV_ICV_HASH}
URL
"${OPENCV_IPPICV_URL}"
"$ENV{OPENCV_IPPICV_URL}"
"https://raw.githubusercontent.com/opencv/opencv_3rdparty/${IPPICV_COMMIT}/ippicv/"
DESTINATION_DIR "${THE_ROOT}"
ID IPPICV
STATUS res
UNPACK RELATIVE_URL)

"https://raw.githubusercontent.com/opencv/opencv_3rdparty/${IPPICV_COMMIT}/ippicv/" 修改為 "file:///data/app/3rdparty "

還要 comment 一下腳本中把 tar 解壓到 src 的步驟。

OpenCV

1
2
CMakeFiles/Makefile2:4315: recipe for target 'modules/videoio/CMakeFiles/opencv_videoio.dir/all' failed
make: *** [all] Error 2

videoio 一般是 FFmpeg 錯誤,沒有配置好 share 或者沒有把路徑添加到環境變量。

Docker

簡介:Docker 入門教程 - 阮一峰的网络日志

https://docs.docker.com/get-started/

https://docs.docker.com/engine/reference/commandline/docker/

Image

Docker 把所有所需文件(系統環境、應用程序及依賴)打包在一個 Image 二進制文件中,通過 Image 文件可以創建 Container。他們的關係類似於各種語言中 Class 和 Instance 的關係。打包好的 Image 可以被複製到其它機器中運行,獲得完全相同的運行環境。

DockerHub

DockerHub 上有大量已經製作好的 Image 文件,通過 docker pull docker image pull 命令可以抓取文件,例如:

1
docker pull nvidia/cuda:9.2-base-ubuntu16.04

就得到一個由 NVIDIA 發佈的,包含 ubuntu 16.04 和 cuda 9.2 環境的 Image。

使用 docker image lsdocker images 可以列出本機所有 Image 文件,使用 docker image rm [imageName]docker rmi [imageName] 刪除。

1
2
REPOSITORY     TAG                     IMAGE ID        CREATED        SIZE
nvidia/cuda 9.2-base-ubuntu16.04 460f66f4885a 2 weeks ago 144MB

Dockerfile

通過 Dockerfile 可以自定義地製作一個符合所需的 Image 文件,一個簡單的 Dockerfile 示例如下:

1
2
3
4
5
FROM nvidia/cuda:9.2-base-ubuntu16.04
RUN apt-get update && apt-get install -y git
RUN mkdir /app
WORKDIR /app
COPY . /app
  • FROM 繼承一個基礎鏡像,

  • RUN 運行一些 shell 指令,所有結果(對文件的改動)都會打包進 Image 中

  • WORKDIR 切換當前目錄,相當於 cd

  • COPY 把本地的一些文件複製打包進 Image 中指定位置

docker build -t <ImageName>:<Tag> ..

. = Dockerfile Path,在 tag 前加入私有倉庫的地址(類似 xxxxx.com/user-dev/tag:version)在之後 push 時會自動 push 到這個地址,否則是 hub.docker.com。

Export/Load Image

docker save nginx:latest > /root/docker-images/nginx.tar

docker load --input /root/docker-images/nginx.tar

Upload to DockerHub

首先需要 login docker login -u=[username] (-p=[Password]) [custom dockerhub address],不帶網址則登陸到官方 Hub。

可能需要重新 Tag 一下鏡像,docker tag 287b0bcf82c9 nginx:latest,可更改名稱和 Tag。

最後 docker push [Image]:[Tag]

Container

各種方法得到了一個 Image 後,即可創建若干個 Container。

docker run -itd -v $PWD:/workspace -p 8000:3000 --shm-size=1024m --name torch nvidia/cuda:9.2-base-ubuntu16.04 /bin/bash

  • -it 容器的 Shell 映射到當前 Shell,在當前 Shell 輸入的命令會傳入容器

  • -d 退出 Shell 後保持後台運行

  • -v 將本機目錄映射到容器內目錄

  • -p 容器內的 3000 端口 映射到本機的 8000 端口

  • --shm-size 指定共享內存的大小,默認的 64M 在 PyTorch 的 DataLoader 中會報錯 RuntimeError: DataLoader worker (pid 1378) is killed by signal: Bus error. It is possible that dataloader's workers are out of shared memory.

  • --name 指定 container 名字

  • /bin/bash 容器啓動後內部第一個執行的命令,啓動 Bash 使得可以使用 Shell

docker container run 會創建一個新的 Container(如果 Image 不存在會自動嘗試 pull),一個 Container 也是一個二進制文件,在 Container 内的任何改動都會保存到這個文件中,Container 退出/停止之後

ctrl+d exit

docker ps docker ps -a

1
2
CONTAINER ID    IMAGE                               COMMAND        CREATED              STATUS                       PORTS           NAMES
847442df5cc7 nvidia/cuda:9.2-base-ubuntu16.04 "/bin/bash" About an hour ago Exited (0) 45 minutes ago jovial_mestorf

docker container start 847442df5cc7 docker attach 847442df5cc7 / docker exec -it 847442df5cc7 /bin/bash,id/name

ctrl+p+q

docker container rm [containerID]

Jupyter and VSCode

Jupyter 和 VSCode 可以遠程連接到服務器作業,然後保存直接更改到服務器上。Jupyter 是啟動了一個 http 服務,然後在網頁上進行編輯,原生 VSCode 用的是 SSH。不管怎樣都是比 Vim 方便。Jupyter 上傳下載文件方便一點,不需要 SFTP 了。VSCode 帶了 Terminal,且有自動補全,各種都好用。

Jupyter

在網上看了一圈,發現都是莫名奇妙的配置方法,麻煩且,我感覺就多人共用一個 root 還是挺常見的吧,直接命令生成新的配置覆蓋不好吧。。其實它可以指定配置文件啟動。把底下的祖傳配置腳本隨便放到哪,然後 jupyter notebook --allow-root -y --ip=0.0.0.0 --config="<path>/jupyter_notebook_config.py" 就好。其實只要有 --ip=0.0.0.0 都不需要後面的 config 它就會啟動一個可以遠程登陸的 kernel,這個 ip 默認是 localhost,寫 0 自動用本機 IP,端口 8888。下面的 config 主要是自定義一個端口和打開 Jupyter 之後的工作目錄,以及獲取環境變量中的 password。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import os
from IPython.lib import passwd

c = get_config()
# default is `localhost`, set to `0.0.0.0` to enable remote login
c.NotebookApp.ip = '0.0.0.0'
# set an unique port
c.NotebookApp.port = int(os.getenv('PORT', 12345))
c.NotebookApp.open_browser = False
# set jupyter workspace dir
c.NotebookApp.notebook_dir = "/data/kotori/workspace"

# sets a password if PASSWORD is set in the environment
# otherwise generate a login token
if 'PASSWORD' in os.environ:
password = os.environ['PASSWORD']
if password:
c.NotebookApp.password = passwd(password)
else:
c.NotebookApp.password = ''
c.NotebookApp.token = ''
# del os.environ['PASSWORD']

運行之後會顯示下面的,它給出的 IP 和域名估計都不對,就 ifconfig 查一下服務器內網 IP,然後用指定的端口和它生成的 token 登陸即可(系統環境中配置了密碼按照上面的配置腳本會自動使用這個密碼)。

1
2
3
[I 15:10:10.848 NotebookApp] Jupyter Notebook 6.1.1 is running at:
[I 15:10:10.848 NotebookApp] http://<machine-name>:12345/?token=286418550b6a1ff2b767ddaeeb0c1dc2c493e774cbfd3c87
[I 15:10:10.848 NotebookApp] or http://127.0.0.1:12345/?token=286418550b6a1ff2b767ddaeeb0c1dc2c493e774cbfd3c87

VSCode

VSCode 裝上 Remote 插件 (ms-vscode-remote.remote-ssh) 可以 SSH 登陸,但是我發現不少地方會在中間做一層跳轉,也就是 SSH 登陸到的只是一台跳轉機而不是真正的服務器,需要用代理 SSH 穿透。

需要一個 Docker 容器,裡面需要有幾個包 apt-get update && apt-get upgrade && apt-get install build-essential openssh-server -y 這個可以直接加到 Dockerfile 中,進入容器時需要映射需要的 Port,可以用 host 模式全部映射出來。

在容器內:

1
2
3
4
mkdir /var/run/sshd \
&& sed -ri 's/^#?PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config \
&& sed -ri 's/UsePAM yes/#UsePAM yes/g' /etc/ssh/sshd_config \
&& echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config

然後 vim /etc/ssh/sshd_configPort 22 那一行解除注釋,改成需要的端口([1024-65536] 沒有在使用的),然後把本機的 ssh pubkey 加入到容器的 ~/.ssh/authorized_keys 中。最後在容器外 docker exec -d <ContainerName> /usr/sbin/sshd -D 啟動 SSH Server。

配置一下本地 VSCode 的 Config ~/.ssh/config

1
2
3
4
5
6
7
Host *
ServerAliveInterval 45
Host remote-rd-04
HostName 10.69.142.19
ProxyCommand nc -x 172.22.123.13:1080 %h %p
Port 12350
User root

Code Server

網頁版 VSCode,在真正的服務器啟動 HTTP 服務,然後客戶端通過一個 HTTP 代理連接服務器(通常用跳轉機就會提供這麼一個 Proxy)。VSCode 本身就是基於 electron.js 的,所以搬到 Web 運行很正常。好處是不用配置 SSH,臨時用別的機器也隨便找個瀏覽器就能用。

下載 code-server 二進制版本:code-server/releases,下載完成解壓縮,然後直接運行 bin/code-server 就會啓動服務並在 ~/.config/code-server/config.yaml 生成一個配置文件:

1
2
3
4
bind-addr: 127.0.0.1:8080                                                                           
auth: password
password: 875b933cf36fcc0d4aff2550
cert: false

將配置文件複製到自己目錄下,修改 bind-addr0.0.0.0:${port} 同 Jupyter 一樣開啓遠程登錄和指定端口。修改 password 或使用 export PASSWORD=${password} 配置環境變量都可以修改密碼,或使用 --auth none 參數啓動,關閉驗證。

安裝插件可以使用 --install-extension ms-python.python 或直接在網頁 VSCode 中正常安裝或下載 .vsix 文件后在左側 Extensions -> Views and More Actions(左上角三個點) -> Install from VSIX…。

之後指定配置文件啓動 bin/code-server --config /data/vscode_config.yaml。它默認打開 Auto Save,和桌面版有點不一樣,所以默認不顯示 unsaved indicator。

Not serving HTTPS

此外,我看到說 1.40 以上已經自帶 Web 版本了,需要從源碼編譯:让 VSCode 在本地 Run 起来

Background 運行

nohup {cmd} > {logfile.log} 2>&1 & 即可。結束可先通過端口查詢進程 netstat -nlp | grep <port> 然後 kill

也可以使用 screen:screen -S ${codeserver} 新建啓動一個新的 screen 會話,在這啓動 code server,ctrl+a+d 退出可回到原 shell 界面,screen -r ${codeserver} 恢復(進入已存在的)screen。

screen -ls 列出所有正在運行的 screen:

1
2
3
4
There are screens on:
12190.vscode (08/10/2020 10:28:29 AM) (Detached)
...
4 Sockets in /var/run/screen/S-root.

screen -X -S {24862} quit 關閉某個 screen。

1
2
3
4
bind-addr: 127.0.0.1:8080                                                                           
auth: password
password: 875b933cf36fcc0d4aff2550
cert: false

將配置文件複製到自己目錄下,修改 bind-addr0.0.0.0:${port} 同 Jupyter 一樣開啓遠程登錄和指定端口。修改 password 或使用 export PASSWORD=${password} 配置環境變量都可以修改密碼,或使用 --auth none 參數啓動,關閉驗證。

安裝插件可以使用 --install-extension ms-python.python 或直接在網頁 VSCode 中正常安裝或下載 .vsix 文件后在左側 Extensions -> Views and More Actions(左上角三個點) -> Install from VSIX…。

之後指定配置文件啓動 bin/code-server --config /data/vscode_config.yaml。它默認打開 Auto Save,和桌面版有點不一樣,所以默認不顯示 unsaved indicator。

Not serving HTTPS

此外,我看到說 1.40 以上已經自帶 Web 版本了,需要從源碼編譯:让 VSCode 在本地 Run 起来

Background 運行

nohup {cmd} > {logfile.log} 2>&1 & 即可。結束可先通過端口查詢進程 netstat -nlp | grep <port> 然後 kill

也可以使用 screen:screen -S ${codeserver} 新建啓動一個新的 screen 會話,在這啓動 code server,ctrl+a+d 退出可回到原 shell 界面,screen -r ${codeserver} 恢復(進入已存在的)screen。

screen -ls 列出所有正在運行的 screen:

1
2
3
4
There are screens on:
12190.vscode (08/10/2020 10:28:29 AM) (Detached)
...
4 Sockets in /var/run/screen/S-root.

screen -X -S {24862} quit 關閉某個 screen。

附:Linux 自帶的幾個命令

查找移動文件

find -name "*.mp4" -exec mv {} ./src \; 會使用每個查找的結果放在 {} 中單獨執行後面的命令,以 \; 結尾。

不過很多命令可直接使用 * 通配,比如 cp mv 不需要額外配合使用 find

排除掉某些文件 ls ori/ | grep -v exclude | xargs -i cp -r ori/{} dst/xargs -i 實現將管道 | 傳遞過來的 stdin 進行處理然後傳遞到命令的參數位置上。

統計目錄下文件數量 ls -l | grep "^-"| wc -l,配合 ls -lR ls -lR prefix* -l 一行一個列出,grep 選取 - 開頭的(文件) 或 d(目錄),wc -l 統計行數。

不同機器 SSH 複製

本地到遠程 scp -r <local_file/dir> remote_username@remote_ip:remote_file/dir,遠程到本地將後面兩個參數反過來。

壓縮包

tar -cvf <filename>.tar <dir_path>c 打包,x 解包,v 詳細信息,f 指定文件。z gz 壓縮,j bz2 (bunzip2) 壓縮,-C <path> 指定解包目錄,如果裡面文件很多可以創建一個目錄給它外面套一层文件夾。

r 追加,find -name "*.mp4" -exec tar -rvf video.tar {} \;,每個命令單獨執行的,所以要用追加。不過這裡 tar -rvf video.tar *.mp4 比較直接。u 替換,使用指定文件替換包中同名文件。

r, u, c, x 選一種模式,f 必須要且在最後;有 gz 後綴加個 z,有 bz2 加 jv 隨意。

unzip -d 指定解包目錄,-q 不輸出詳細信息。

Package Management

Miniconda conda config --set auto_activate_base false,在 ~/.condarc 中配置。

apt list --installed