admin管理员组

文章数量:1531688

文章目录

  • Linux
    • 从服务器获取图形界面
  • Ubuntu系统的一些小问题
  • Anaconda的使用
  • Virtualenvwrapper的使用
  • jupyter的使用
  • cmder的使用
  • Screen的使用
  • VSCode的使用
  • Visual Studio的使用
  • 在非Root的情况下安装各种东西
  • Windows一些生僻的知识点
  • LaTeX语法
  • VMware
  • Qt
  • 运维
Linux

cd home返回到家目录
cd /返回到根目录
cd ..目录向上一级
cd -回到上一个使用过的目录
pwd显示当前目录
ll显示当前目录下所有文件
vim 文件名 使用vim工具编辑文本
一进来是命令模式,除了方向键之外,H J K L四个键也可以进行光标的移动(H左J下K上L右)
I进入编辑模式,自由编辑,按Esc退出编辑模式。编辑完后输入:wq(即write and quit)保存退出。输入:e! 撤销当前编辑的所有内容
行号+G:移动光标至某行行首 0:光标移动到行首 $:光标移动到行尾
gg:回到文档首 G:来到最后一行行首
w:前移一个单词(=ctrl+→b:后移一个单词(=ctrl+←
若显示root@主机名:~#字样,root表示正以管理员身份登录,~表示现在正处于家目录(一般用户为home,管理员用户为root),/表示正处于根目录
sudo 表示用超级用户的权限来操作(super do),如果已经是管理员身份了可以省略sudoapt-get命令会自动到设置好的源镜像中获取所要求的文件,一般下载到/usr/bin文件夹和/usr/lib文件夹。
sudo su可以进入超级用户,通过su 用户名 命令回到普通用户
touch 1.py 新建一个文件
输入cd后连按Tab键可以显示当前目录下的文件夹
rm 文件名:删除文件
使用虚拟机运行Ubuntu时,有的时候切出去了再回来的时候,发现输入不了了,这是要按下Ctrl+Alt键,再点击要输入的位置,就会恢复正常。
查看系统版本:sudo lsb_release -a
查看内核版本:cat /proc/version
i386就是指32位的Ubuntu,AMD64就是指64位的Ubuntu.
Linux中查看系统资源占用情况的命令
du命令用来查看文件的大小,详情请看原文

du -sh .[!.]* # 查看隐藏文件的大小
# .[!.]* 是正则式, 意思是第一位是点, 第二位是除了点以外的字符, 第三位是任意字符或者不存在
# 后面可以再加一个" *"来包括非隐藏文件
# 后面还可以接 sort -h来对占用空间进行排序(sort 的 -k2 可以指明根据第二列来排序)
du -sh .[!.]* * | sort -hr # 显示所有隐藏文件和非隐藏文件的大小并根据占用空间排序
echo .[!.]* # 查看所有隐藏文件

df -lh查看占用的硬盘资源
Linux统计某文件夹下文件、文件夹的个数:

ls -l dirname|grep "^-"| wc -l # 统计某文件夹下文件的个数
ls -l dirname|grep "^d"| wc -l # 统计某文件夹下目录的个数
ls -d */ | wc -l # 也是统计某文件夹下目录的个数
ls -l dirname|grep "^d"| wc -l # 查看某个文件夹下文件夹的个数。
ls -lR dirname|grep "^d"| wc -l # 查看某个文件夹下文件夹的个数,包括子文件夹下的文件夹个数。
ls -l dirname| wc -l # 查看文件夹下所有的文件和文件夹。也就是统计ls -l命令所输出的行数。

如统计/home/han目录(包含子目录)下的所有js文件则:
ls -lR /home/han|grep js|wc -l 或 ls -l "/home/han"|grep "js"|wc -l

说明:
ls -lR
长列表输出该目录下文件信息(R代表子目录注意这里的文件,不同于一般的文件,可能是目录、链接、设备文件等)
grep "^-"
这里将长列表输出信息过滤一部分,只保留一般文件,如果只保留目录就是 ^d
wc -l
统计输出信息的行数,因为已经过滤得只剩一般文件了,所以统计结果就是一般文件信息的行数,又由于一行信息对应一个文件,所以也就是文件的个数。
如果只查看文件夹
ls -d 只能显示一个.
find -type d 可以看到子文件夹
ls -lF |grep / 或 ls -l |grep '^d' 只看当前目录下的文件夹,不包括往下的文件夹
ps -ef | grep firefox | grep -v grep | cut -c 9-15 | xargs kill -s 9

grep命令:表达式匹配,常用于从大量输出信息中提取感兴趣的部分

ll | grep ".jpg" # 从当前目录中筛选出所有jpg文件的文件信息
ll | grep ".jpg" -c # 计算当前目录下jpg文件的总数,-c是统计匹配结果的行数
ll | grep ".jpg" -i # 从当前目录中筛选出所有非jpg文件的文件信息
ll | grep -E "j|p" # -E把双引号内的内容解释为正则表达式,从而可以用|号进行“或”匹配

cut命令:对输出信息按照某个分隔符进行切割,取其中的某一块,例如:

# 搜索占用9999端口的程序,如果是blender,则找到返回其进程id
lsof -i:9999 | grep blender | cut -d' ' -f2 
# 搜索占用9999端口的程序,如果是blender,则将其杀死
lsof -i:9999 | grep blender | cut -d' ' -f2 | xargs kill
cut -d' ' -f2 # 以空格为分隔符
cut -d: -f2 # 以:为分隔符

标准流的重定向:
在没有重定向之前,标准输出跟标准错误都默认输出到屏幕(terminal)上,重定向之后将它们保存到文件里面,并不再出现在屏幕上

command >> out.txt # 执行command命令,把标准输出保存到out.txt,标准错误仍打印到屏幕上
command 1>>out.txt 2>>err.txt # 执行command命令,把标准输出保存到out.txt,标准错误保存到err.txt
# 注意2跟>>中间不能有空格,如2 >>err.txt会报错,其他位置可以有空格
command >> join.txt 2>&1 # 执行command命令,把标准输出和标准错误都保存到join.txt(分析:先指定标准输出的重定向目标,而后把标准错误重定向到标准输出。2>&1一定要在>>的后面,次序颠倒会报错)
# 注意2跟>&中间不能有空格,其他地方无所谓
command >> /dev/null 2>&1 # /dev/null是一个特殊的文件,就像一个无底洞一样,写到这里就相当于丢掉这些信息,既不显示到屏幕上,也不保存到任何一个文件里面

>> a.txt如果在程序运行时修改a.txt的文件名为b.txt,则程序会继续把数据写入到b.txt中,而不是建立一个新的a.txt;如果删除a.txt,程序也不会再生成新的a.txt。这点跟重复with open+fp.write的效果还是有点区别的。我个人的理解是,>>>相当于是连了一条管道到a.txt,如果a.txt改名了,这个文件对外的名字变了,但这条管道依旧连在那里没有变化,所以写入就会写到新的b.txt中;而如果把原有的文件删除,就相当于是把那条管道的出口处给删了,所以就看不到任何新数据了。
参考链接

判断文件是否存在(参考链接):

if [ -s "$HOME/.Xauthority" ]; then
echo exist
fi

shell的文本处理
在获取原始的文本信息之后,我们通常需要进行一些清洗跟筛选,得到我们真正需要的数据。例如svn的更改信息:A xxx yyy.png表示新增了一个文件名为xxx yyy.png的文件,我们想要提取文件名,一般会用到awk命令。awk默认以空格为分隔符,如果文件名中含有空格,直接$2只能拿到xxx,拿不到后面的部分。因此需要这样写(参考链接):

# -F " "表示以空格为分隔符,NF是split出的段数,for循环的含义是打印从第2段到最后一段
command | awk -F " " '{for (i=2;i<=NF;i++)printf("%s ", $i);print ""}' 

一般对每一行文本做处理常用的命令是for f in $files,但是如果行中有空格,也会被for循环分隔开,为了完整地保留整个文件名,一个方法是使用内部字段分隔符,这个我没细看;另一个方法是改用while read

command | while read f; do
    # 每一行的字符串保存在变量f里
    echo $f
    done

从多行字符串变量读取就这样写:

while read f; do
    echo $f
    done <<< $files

awk命令:处理带分隔符的行,分段判断并处理。
参考链接1,参考链接2

xargs命令:xargs kill -s 9中的xargs命令是用来把前面命令的输出结果(PID)作为kill -s 9命令的参数,并执行该命令。kill -s 9会强行杀掉指定进程
xargs与cp结合:cp有两个参数,需要用{}指定将args的参数放在哪个位置:ls *.* | xargs -i cp {} dst_path
xargs一个参数用于多条命令,需要借助sh -c
cat /tmp/users | xargs -i sh -c “useradd --create-home --no-log-init --shell /bin/bash {} \ && adduser {} sudo”,从文件中逐行获取用户名,并创建该用户,并添加进sudo用户组。

Linux下重命名文件或文件夹(mv命令与rename命令)

sed命令:对文件中的内容按规则进行批量修改,sed详解

# 将文件filepath中的所有before替换为after,-e表示输出到标准输出流中,不替换文件内容,
# 可用于正式操作前的检查。s表示替换,还有其他功能的字母,g表示全部,无g则只对每行的第一个匹配做操作
sed -e 's/before/after/g' filepath
# -i表示替换后写入文件,文件filepath将被更改,危险操作
sed -i 's/before/after/g' filepath
# 想对空格做替换也是直接把空格放里头
sed -e 's/ /after/g' filepath
# 还可以指定行号,直接将某一整行修改为after
sed -e '42c after' filepath
# 还可以指定只对包含某个字符串的行做处理,例如对包含test字符串的行末尾添加000
sed -e '/test/ s/$/000/' filepath
# 将以test开头的行整行替换为after(如果不加行首限制符^,全域通配符.*很容易出现误删)
sed -e '/^test/ s/.*/after/' filepath

lspci  | sed -n -e '/VGA compatib.*NVIDIA/s/^\(..\):\(..\).\(.\).*/\1:\2.\3/p'

貌似如果要限定只对某些匹配行做处理,就在第一段写上判断条件,比如42c指定行号,或者/test/指定含有字符串test的行,然后接空格再写做什么操作,比如s/$/000

参考链接
sed命令在匹配某特定字符串的行尾添加字符串
sed命令在匹配某行后替换整行
用一个文件的匹配行替换另一个文件的匹配行,还没看懂,先放在这

source: 执行脚本
执行shell脚本有很多种方式,比如. ./xx.sh./xx.shsource ./xx.sh等。
它们的区别在于,. ./xx.shsource ./xx.sh等价,都是在当前终端下执行脚本,如果xx.sh里面有cdexport等命令,脚本执行完成之后,当前的工作目录会被切换,环境变量也会被更新;./xx.sh方式是新开一个终端执行脚本,脚本执行完成之后不会影响当前的工作目录和环境变量,这种方式要求xx.sh有可执行权限x。

scp: 用于远程传输文件
在A服务器上操作,将B服务器上/home/lk/目录下所有的文件全部复制到本地的/root目录下,命令为:scp -r root@43.224.34.73:/home/lk /root
反过来, 在A服务器上将/root/lk目录下所有的文件传输到B的/home/lk/cpfile目录下,命令为:scp -r /root/lk root@43.224.34.73:/home/lk/cpfile
若需指定端口则在scp后添加-P port参数
详见:scp命令详解

rsync:一个好用的文件同步命令,增量同步,比单纯cp更快,更准确,还可以输出过程的详细信息
rsync -a --delete source_root/dirname/ destination_root/dirname/:结果上等价于cp -r source_root/dirname/ destination_root/dirname/,但是速度会更快,因为rsync只对修改时间和文件大小不同的文件做处理,不会全都拷贝一次,各参数含义请看教程。
PS:在正式rsync之前,为了防止手残,最好先加上nv参数:rsync -anv --delete source_root/dirname/ destination_root/dirname/,它会模拟运行一次(不会真的覆盖文件),把即将执行的操作打印出来,我们确认无误后再去掉nv参数重新运行

从Windows传文件到Linux服务器上:使用WinSCP工具即可
添加一个ppa源:sudo add-apt-repository ppa:xxxxx
添加源之后要update一下才会生效:sudo apt-get update
删除某个ppa源:sudo add-apt-repository -r ppa:xxxxx
Ubuntu 安装 .bundle 文件

ifstat查看当前上传下载速度

Linux开机自动挂载磁盘
Ubuntu手动释放缓存,清理内存cache(参考链接):

sudo su
# 多次执行sync
sync && sync && sync \
&& echo 3 > /proc/sys/vm/drop_caches \
&& free -h

一般docker基础镜像的ulimit -c值是unlimited,它会在程序意外中断时(如Ctrl+C)保存一个core文件保留案发现场,供后续开发者复盘研究,但它会占用内存的缓存,free -h时会看到cache的增大,频繁Ctrl+C会越来越大,因此我们通过ulimit -c 0让它不要保存core文件,节约缓存(core dump讲解,关闭core dump)。

修改硬盘的卷标:首先用df命令查看某个名称的硬盘对应的是/dev里的哪个文件;然后使用e2label /dev/yourpartition "mydiskname" 来修改卷标. 适用于ext2/3/4类型的硬盘. 如果是NTFS或fuseblk类型的硬盘应使用sudo ntfslabel /dev/sda2 "mydiskname" 。如果不知道分区的文件系统类型,可以通过df -T命令查询
相关链接:Ubuntu调整分区大小
周期性执行某个命令:watch -n 10 command
对某个目录下多个子目录的图像总数量保持关注:watch -n 1 "ls -R | grep ’jpg‘ -c"

Ubuntu环境下安装nodejs和npm
Linux系统修改PATH环境变量方法

Ubuntu下如何解压缩zip,tar,tar.gz,tar.bz2文件(原文链接,参考链接1):

tar 解包:tar xvf FileName.tar 打包:tar cvf FileName.tar DirName
(注:tar是打包,不是压缩!)
.gz 解压:gunzip FileName.gz 压缩:gzip FileName
.tar.gz 解压:tar zxvf FileName.tar.gz -C DirName 压缩:tar zcvf FileName.tar.gz DirName
.bz2 解压:bunzip2 FileName.bz2 压缩: bzip2 -z FileName
.tar.bz2 解压:tar jxvf FileName.tar.bz2 压缩:tar jcvf FileName.tar.bz2 DirName
.bz 解压:bunzip2 FileName.bz
.tar.bz 解压:tar jxvf FileName.tar.bz
.Z 解压:uncompress FileName.Z 压缩:compress FileName
.tar.Z 解压:tar Zxvf FileName.tar.Z 压缩:tar Zcvf FileName.tar.Z DirName
.tgz 解压:tar zxvf FileName.tgz
.tar.tgz 解压:tar zxvf FileName.tar.tgz 压缩:tar zcvf FileName.tar.tgz FileName
.tar.xz 解压:tar -xvf FileName.tar.xz 压缩:tar -cxzf FileName.tar.xz DirName
.zip 解压:unzip -d DestFolder FileName.zip 压缩:zip -ry FileName.zip DirName-y保持软链接
.rar 解压:rar e FileName.rar DirName(不加DirName则解压到当前目录) 压缩:rar a FileName.rar FileName1 FileName2
.lha 解压:lha -e FileName.lha 压缩:lha -a FileName.lha FileName
解压rar文件:要先安装个东西:sudo apt-get install rar unrar
unrar e test.rar 解压该压缩包里的所有文件
rar a test.rar test 将文件夹压缩成一个rar包

Linux命令ll输出后各个字段的含义
蓝色的名字是目录
wget命令用于下载文件,wget命令
wget -rnp -nd -q ip/scripts/ -A *.sh,*.py -P /usr/local/scripts/把服务器上scripts/目录下的.sh文件和.py文件拷贝到/usr/local/scripts/目录下,-rnp递归拉取整个目录但不拉取上级目录,-nd不创建目录结构,直接拷贝到当前目录
-A只拷贝某些文件格式(否则会拷过来一堆html文件),-P指定拷贝目的地
find命令用于查找文件,find命令
find ./ -name "xxx*.jpg"在当前目录下查找以xxx为开头的jpg文件
Linux系统下查找最近修改过的文件

ps命令查看进程状态(原文链接):
D 不可中断 Uninterruptible sleep (usually IO)
R 正在运行或在运行队列中等待
S 中断, 休眠中, 受阻, 在等待某个条件的形成或接受到信号
T 停止或被追踪 (进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行)
Z 僵死 (进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
W 进入内存交换(从内核2.6开始无效)
X 死掉的进程

< 高优先级
N 低优先级
L 有些页被锁进内存
s 包含子进程
+ 位于后台的进程组;
l 多线程,克隆线程 multi-threaded (using CLONE_THREAD, like NPTL pthreads do)

输出中的TTY值指的是从哪个终端执行的命令,比方说在一个终端中执行ssh命令并保持,那么ps中就会出现一个bash跟一个ssh命令,它们的TTY值是相同的,如pts/19
一般ps pid就能看到是哪个命令启动的这个进程,如果命令太长超过一行,则可以用ps aux | grep pid来显示完整内容
a 显示所有进程
u 可以选定某个用户(缺省是自己),并显示执行命令的用户信息
x 连同没有控制tty的进程也一并输出出来
https://blog.csdn/ffzhihua/article/details/88400044
按内存升序排列:ps aux --sort=+rss
按cpu降序排列:ps aux --sort=-%cpu

linux下查看线程数的方法:
通过/proc伪文件系统来查看线程数,执行cat /proc/{pid}/status,其中Threads后面跟的就是线程数。
[总结] linux下查看线程数的方法
如何验证 ulimit 中的资源限制?如何查看当前使用量?
top命令VIRT,RES,SHR,DATA的含义
top -H -p pid可以查看进程下面的线程
Linux中Python应用CPU占用高问题排查
nvidia-smi更高级一点的debug方法:先ps -aux | grep username,找到对应的sh run.sh命令或者python xx.py命令,然后cat /proc/{pid}/status观察其进程数是否异常大;fuser -v /dev/nvidia*命令可以查看自己在某张显卡下面开的进程,有时候nvidia-smi显示的只是一部分,还有一些在卡下面活动,但是nvidia-smi的时候没有显示出来,看看有没有造成进程积压得越来越多什么的。

多用户的情况下,一般软件安装在usr下,软件执行文件的位置位于/usr/bin目录下,通过软件中心安装的软件,软件下载包位于/var/cache/apt/archives/。软件的配置(如python的一些库是有分版本的,不同的用户可能用到的是不同的版本)要放在各个用户的家目录下,位于home/用户名

家目录下一般应有.profile文件和.bashrc文件,前者在进入系统时首先被执行,在语句中调用了.bashrcbashrc包括一些如环境变量PATH等的配置项。把软件的目录放在PATH下面后,才能在任意目录直接输入软件名调用软件(如python)。
用户登上服务器或通过docker rundocker exec(不包括docker attach)进入容器时执行脚本:在~/.bashrc中添加sh do_something.sh即可,其他设置语句如ulimit -c 0也如此做。

-sh用于设置每个用户使用的shell。
which命令:在PATH变量指定的路径中搜索某个系统命令的位置并且返回第一个搜索结果,常用于查看某个系统命令(如python)执行的是哪一个位置的命令。
一种快速查看软件目录的方法:先执行该程序,然后用命令ps -e, 找到对应的程序名字(已经知道名字的可直接跳过),最后用find命令寻找对应文件的位置(记得加上sudo,不然会搜到一堆奇奇怪怪的东西)
软件商店出问题了,软件安装不上,可以尝试运行sudo apt-get install -f命令,说不定就好了。
在终端中按下ctrl+z,可以中断当前的进程,常用于输出太快看不清楚时暂停一下;看完要继续运行则输入fg命令。另外一个应用是:在使用vi编辑一个文件时,需要执行shell命令查询一些需要的信息,可以使用ctrl+z挂起vi,等执行完shell命令后再使用fg恢复vi继续编辑你的文件。如果中断了多个进程,则可以使用jobs命令显示当前暂停的进程,然后fg 2恢复第2个进程。
Linux查看电脑各种硬件的信息:

# check the cpu
cpu_num=$(cat /proc/cpuinfo | grep -i "model name" | wc -l)
echo "There are $cpu_num cpu at total:"
lshw -class processor
echo " "

# check the memory
echo "Memory:"
free -h
echo " "

# check the network card
echo "Network card:"
lspci | grep -i Ethernet	
echo " "

# check the gpu
gpu_num=$(nvidia-smi | grep "000000" | wc -l)
echo "There are $gpu_num gpu at total:" 
nvidia-smi --query-gpu=gpu_name,gpu_bus_id,memory.total --format=csv
echo " "

# check the hard disk
# use "sudo apt install smartmontools" to install it
echo "Hard disk:"
# -a means show all SMART information for device
sudo smartctl -a /dev/sda | grep -i "Device Model"
sudo smartctl -a /dev/sda | grep -i "SATA Version"
# smartctl -H /dev/hda # check its healthy status
echo " "

关于端口
lsof -i:8888 查看是哪个进程在占用8888端口
sudo netstat -ap | grep "12345" 查看进程12345占用了哪个端口
netstat -ntpl查看开放的tcp端口(参考链接)
ufw allow from xx.xx.xx.xx to any port 12345:12350 proto tcp表示向xxip地址开放12345到12350端口,支持tcp协议,需要sudo
nmap是常用的端口扫描工具,nmap localhost -p 1-65535扫描自己的所有端口,参考链接

firewalld防火墙的基本用法:
对某个ip开放某个端口:firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.142.166" port protocol="tcp" port="5432" accept"
然后应用这个更改:firewall-cmd --reload,就可以了。
查看目前已有的规则:firewall-cmd --zone=public --list-all
删除某条规则:firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.142.166" port protocol="tcp" port="11300" accept",跟添加规则的差别只有add这个词换成了remove
参考链接1,参考链接2,参考链接3
给docker配置firewall防火墙,没搞懂,没成功,docker会在firewall收到数据之前接收到数据包,所以firewall不起作用。firewall其实就是iptables封装了一层,比较细致的定制还是直接用iptables设置。
重置firewalld防火墙:搞着搞着搞坏了,firewall-cmd --state不管怎么搞都是failed,尝试重置。首先cd /etc/firewalld/,找到那些修改日期是今天的目录和文件,进去看看是不是有自己敲下的命令,我这次删掉了/etc/firewalld/zones/etc/firewalld/direct.xml(主要应该是后者的锅,删zones/之前最好备份一下里面的东西),然后iptables -Xiptables -Fiptables -Z,再systemctl restart firewalld,应该就恢复running的状态了。

iptables防火墙的基本用法:
docker与iptables的联动官方文档
首先安装docker的时候会在firewall下生成一个名为docker的zone,然后docker容器与外部通信使用的网卡名称叫做docker0,它会插入这个zone的interface,在firewall-cmd --list-all-zones时可以看到docker这个zone的interfaces一栏有一个docker0。
根据官方文档,docker跟Iptables的链(chain)的关系是,它使用DOCKER链,如果用户需要定制一些规则,应当在DOCKER-USER链中写入。
iptables -I DOCKER-USER -i docker0 ! -s 192.168.1.1 -p tcp --dport 8443 -j DROP表示把某个ip访问8443端口的tcp数据包全部丢掉,不加--dport 8443表示针对所有端口,不加-p tcp表示面向所有协议,不加-s 192.168.1.1表示对所有ip有效
iptables命令即写即生效,不需要类似firewall-cmd --reload的操作。
iptables-save可以查看规则,不过这里看到的很多东西很乱。
iptables -L就清晰多了,按链书写,找到DOCKER-USER,看看刚才的设置对不对。后面打印出来的"tcp dpt:18100"就是端口号,有时候不是数字是一串字符,比如"tcp dpt:pcsync-https",是因为这个端口比较有名,所以用服务名称代替端口名,并不是端口没有设置成功哦。
iptables -L DOCKER-USER --line-numbers只看某个链,且给出行号,方便后面删除规则
iptables -D DOCKER-USER 1删除列表里的第一条规则,参考链接
新设定的规则会放在最上面,判断时从上往下走,遇到第一条符合的规则就结束
iptables的DNAT

用户从外部向容器监听的端口发送http请求时,首先经过的是eno0网卡,也就是真实网卡,这是在public域里,默认拒绝所有请求,因此必须在public域中设置一条准许某个ip访问某个端口的规则,才进得来;而websocket请求是在8443端口,这是一个常用端口,而且由于某种原因被做了DNET,网卡收到数据包后直接转发给docker域里的docker0网卡了,所以这时在public域中设定的规则并不能应用到这些数据包上,当前所有ip都可以访问8443端口。接下来应该在docker-user链中添加规则,才能阻止其他ip访问这个端口,在public域或docker域设定是没用的。

还是直接对docker-compose.yaml配置文件做修改靠谱一点,不然容器关闭和开启的时候又会去修改iptables,可能导致白改一趟。修改方法

ssh原理与运用
ssh免密登录:安全起见,公网ip最好配个密钥,避免被爆破。首先在本机的~/.ssh目录下运行ssh-keygen -t rsa生成公钥和私钥,然后再运行ssh-copy-id user_name@server_ip,把公钥拷到服务器上,再次登录就不需要密码了。

env:列出所有环境变量

从服务器获取图形界面

比如我们通过ssh或者XShell连上了服务器,用matplotlib画图的时候发现plt.show()之后看不到图,但这个需求很常见,因此有必要给服务器配置好X11图形界面。这里我们以本机为Windows系统为例,用XShell作为ssh工具(Windows直接ssh -X没办法显示图形界面),选用Xming-Server来接收服务器的图形界面输出。
配置Xming-Server:下载安装Xming,然后把它开起来就可以了。
配置XShell:右键某个会话,属性——连接——SSH——隧道,勾选转发X11连接到,选择第二个X DISPLAY,后面的localhost:0.0保持不动。
运行测试命令:

# 如果xclock提示未安装就安装一下x11-apps这个包
sudo apt-get install x11-apps
xclock

预期要能弹出一个Xming的窗口,里面是一个时钟,有的话说明我们配置成功了。

接下来实现对matplotlib画图的支持:这里以还没装python的情况为例:

# 安装python开发套件,如果这一步报错
# libgirepository-1.0-1: Breaks: python-gi (< 3.34.0-4~) but 3.26.1-2ubuntu1 is to be installed,
# 就sudo apt remove python-gi把这个包先卸载了
sudo apt install -y python3.9-dev python3.9-distutils python3-pip && apt-get clean
python3.9 -m pip install -i https://pypi.douban/simple/ matplotlib
# 要在服务器上安装tkinter,不然运行下面的python程序的时候会报错:
# ImportError: Cannot load backend 'TkAgg' which requires the 'tk' interactive framework, as 'headless' is currently running
sudo apt-get install python3-tk

然后写一个简单的测试小程序:

import matplotlib
matplotlib.use("TKAgg")
from matplotlib import pyplot as plt

x = list(range(10))
y = list(range(10))
plt.plot(x, y)
plt.show()

保存成test.py后运行python test.py预期要能弹出一个Xming的窗口,画出一条蓝色直线。至此matplotlib也可以正常使用了~

本机为Ubuntu系统的,本地及远程的图形界面配置看这里,一般不需要配置什么,直接在ssh的时候加上-X参数就能启用图形界面了。

进阶:从服务器的容器上获取图形界面
首先要完成上文对“从服务器获取图形界面”的配置。
接着在宿主机(也就是服务器)运行xhost +local:root,然后在docker run的时候添加三个参数:

-v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY \
-v ~/.Xauthority:/root/.Xauthority:rw \

就可以了,参考链接
Windows本机开容器用GUI暂时搞不定,那个display有问题。
Ubuntu本机开容器用GUI跟在宿主机开容器用GUI是一样的操作。
注意如果docker run的时候添加了--hostname参数,应当保证hostname存在于xauth list的输出中,否则需要手动添加xauth项

后面又遇到了xauth的问题,重新扒拉了一下资料,回来填坑:
本机连接服务器时,本机是X11 Server,服务器才是Client,本机在服务器的.Xauthority文件末尾写入一条形如
"<hostname>/unix:15 MIT-MAGIC-COOKIE-1 <key>"的信息,同时将新开的这个终端的DISPLAY环境变量设为localhost:15,此时lsof -i:6015可以看到有进程处于监听状态。此时在宿主机上运行xclock,理应正常输出图像。需要注意的是,不是每次新开终端都会新写一条.Xauthority信息:每个连接的终端占用一行,每多启动一个终端就多写一行,端口号递增,终端退出不会擦除这行信息,如果中途有的终端退出了,再新开终端就会复用之前的信息,相当于补空位。用xauth remove <hostname>/unix:15命令可以手动移除这行信息,移除之后使用该端口的宿主机终端就无法再成功运行xclock。xauth add <hostname>/unix:15 MIT-MAGIC-COOKIE-1 <key>可以添加一行信息,但是我们无法得知key的正确值,直接用其他行的key值是不可行的,所以手动add也是不可行的。
然后回到容器这边,由于信息没有自动擦除,时间一长,文件中的信息可能会过期(这个只是推测),当一个容器启动了好几个月之后突然想用一下图形化界面,很可能就用不了了。一个简单的处理办法是将所有终端全部退出,然后将所有信息都remove掉,再连回来,目的是让容器里配的DISPLAY端口获得一个新的key。当宿主机使用这个端口能正常xclock之后,重启容器,然后容器就能正常使用图形化界面啦!需要留意的是,将所有信息全部remove掉可能导致VSCode ssh连接一直报异常,需要关闭所有VSCode窗口然后重新连接,再不行就重启电脑,就能恢复了。
参考资料:xauth讲解,X11-forwarding讲解

Ubuntu系统的一些小问题

Ubuntu无法安装vim:Package vim is not available, but is referred to by another package.

Anaconda的使用

下载Anaconda
安装后配置一下环境变量Path,添加下面三个路径(以安装路径为D:\Anaconda3为例):
D:\Anaconda3
D:\Anaconda3\Scripts
D:\Anaconda3\Library\bin
然后打开cmd输入conda --version,能看到版本就说明配置成功了。

conda管理python环境:
conda config --show 查看conda的所有配置
conda info -e 查看当前的虚拟环境目录
conda create -n env_name numpy matplotlib python=3.5 创建新环境,env_name是我们给新环境起的名字,numpy那些是我们想在创建环境时一起装的库,python=3.5指定python版本
source activate env_name 切换到虚拟环境
source deactivate env_name 退出环境
conda remove -n env_name --all 移除环境
conda install 包名 安装包,要装在哪个环境下就得先切换到哪个环境
conda install --yes --file requirements.txt 安装文件中指明的依赖项,与pip install -r requirements.txt类似
conda remove 包名 卸载某个包
conda list 查看当前环境下已经安装的package
conda config --add channels 网址(可不加单引号) 添加一个下载用的网址
conda config --remove channels 网址(可不加单引号) 移除某个下载通道
添加清华镜像源
conda 使用本地包安装:
发现一些安装包采用一些特定源获取时,因为网络问题下载不下来(比如低版本的pytorch)。我们可以自己到对应网站上把包下载到~/anaconda3/pkgs/目录下,然后执行conda install --use-local pkg_name,就可以了
PS:conda只能安装tar.bz2格式的包,如果是torch这种whl文件,要用pip install来安装
原文链接

Conda自动进入虚拟环境base的解决办法

conda发神经安装啥都报错,报错消息一长串,最后一句是json.decoder.JSONDecodeError: Unterminated string starting at: line 184947 column 5 (char 5586731)。解决方案
遇到包版本不对的情况:ERROR: Package ‘ipython’ requires a different Python: 3.6.12 not in ‘>=3.7’。解决的奇妙办法
conda回退版本
有一次在win10上安装anaconda后没有出现conda.exe,只有一个_conda.exe,我把它重命名为conda.exe后其行为类似原来的conda.exe,然后设好环境变量,结果在conda create之后无法conda activate,也无法conda init,最后发现在开始菜单里的“Anaconda PowerShell Prompt”点开却是可以用的,我也不懂是怎么回事,总之就只能从那里进去了,不能从cmd或者powershell进去,暂时先这么用着了。

Virtualenvwrapper的使用

virtualenv 是一个创建隔绝的Python环境的工具。virtualenv创建一个包含所有必要的可执行文件的文件夹,用来使用Python工程所需的包。virtualenvwrapper是virtualenv的升级版,它把你所有的虚拟环境都放在一个地方,方便对虚拟环境集中管理。

pip install virtualenv 安装virtualenv
pip install virtualenvwrapper 安装virtualenvwrapper (Windows使用pip install virtualenvwrapper-win)
linux上安装后要设置环境变量:
mkdir ~/.virtualenvs
vim ~/.bashrc,在文件末尾添加

export WORKON_HOME=~/.virtualenvs
source ~/.local/bin/virtualenvwrapper.sh

然后source ~/.bashrc即可

mkvirtualenv env_nameWORKON_HOME环境变量指定的目录下创建一个新环境。如果没有配置该环境变量,默认目录是C:/
mkvirtualenv --python=/usr/local/python3.5.3/bin/python env_name 在创建环境时指定解释器版本
workon 查看当前的虚拟环境目录
workon env_name 切换到虚拟环境
deactivate 退出虚拟环境,回到系统默认的Python解释器,包括已安装的库也会回到默认的
rmvirtualenv venv 删除虚拟环境
Virtualenv与conda不同的一点是,conda安装库是conda install,而Virtualenv仍然是pip install

/usr/bin/python: No module named virtualenvwrapperd 的解决方案
virtualenv is not compatible with this system or executable 未解决

jupyter的使用

安装Jupyter:pip install jupyter notebook
运行Jupyter: cmd中输入jupyter notebook,会自动弹出。
命令行下通过命令jupyter notebook启动jupyter,现在默认端口是8888不用改,启动之后在浏览器访问http://120.77.207.13:端口号即可进入服务器的目录。在哪个目录下启动jupyter,进入之后就到那个目录,不能访问上级目录,可以访问下级目录。new一个py文件,会生成ipynb文件,使用的是交互式编程,回车换行,写完一段后Ctrl+回车执行本段,比把一堆代码复制粘贴到python命令行或者py文件中后再执行快多了,而且一段代码可以反复修改执行。菜单栏File里可以保存并设置checkpoint,可以回档。
jupyter notebook password 设置密码(如果尚未生成过配置文件,则先运行jupyter notebook --generate-config 命令生成配置文件)
默认只有本机能连上jupyter,如果想要从其他主机连上服务器上的jupyter,则需要修改一下~/.jupyter/jupyter_notebook_config.py,在200行左右,把c.NotebookApp.ip = 'localhost' 改成 c.NotebookApp.ip = '*'即可(如果py文件改完还不行,就改同名的json文件,添加一句"ip": "*")。如果修改成功,lsof -i | grep 端口号应该看到LISTEN的是*:端口号,而不是localhost:端口号
Jupyter Notebook的27个窍门,技巧和快捷键
Jupyter Notebook自带的pdb调试工具 通过%pdb魔法命令启动

在函数名后面的括号里按下Shift+Tab键可以查看函数的调用格式。
有没有想过一个场景,你的jupyter notebook是导出一个报告给业务人员看的,他们不想看到那些密密麻麻的代码,只想留下markdown和图表,在jupyter notebook加入下面这段代码就好:

import IPython.core.display as di 
di.display_html('<script>jQuery(function() {if (jQuery("body.notebook_app").length == 0) { jQuery(".input_area").toggle(); jQuery(".prompt").toggle();}});</script>', raw=True)

jupyter的清屏语句

from IPython.display import clear_output as clear
clear()

若下载好了某个库,在黑框框下可以import它,但在jupyter里却不行,可能是路径没设置好,需要添加一条全局路径:sys.path.append(‘库的路径’)
PyCharm也可以打开.ipynb文件

如何在Jupyter Notebook中使用Python虚拟环境?
从Virtualenv改用Anaconda之后,新装的jupyter出现了一点问题:python命令出来的版本,跟jupyter里面的python版本不一样(表现为终端的Pythonimport成功的库,在jupyter里面找不到)。找了半天看到了一个好东西,多装一个库,jupyterl在创建.ipynb文件的时候就能自由选择用哪个虚拟环境了,也即即使我们是在A环境下启动了jupyter,我们也可以使用B环境下的python来编译运行ipynb,岂不美哉!
安装nb_conda:conda install nb_conda,然后重启jupyter,在new—notebook那里就可以看到不同的虚拟环境了,美滋滋啊!

jupyter用着用着突然’_xsrf’ argument missing from POST无法保存,解决方案

cmder的使用

已经放进全局变量,直接Win+R输入cmder即可启动。
如果想要添加自定义别名命令,可以修改cmder目录下的user-aliases.cmd文件(Windows环境下)
在CMD中输入bash,则可以进入Linux子系统,在shell中输入exit则退回CMD状态。
所有驱动器将会Mount到/mnt/c/目录下(c是驱动器名字)。
Cmder的一些配置(右键快捷启动)

Screen的使用

系统管理员经常需要SSH 或者telent 远程登录到Linux 服务器,经常运行一些需要很长时间才能完成的任务,比如系统备份、ftp 传输等等,在此期间不能关掉窗口或者断开连接,否则这个任务就会被杀掉,一切从头再来。Screen正是为了解决这个问题而来的。只要Screen本身没有终止,在其内部运行的会话都可以恢复。这一点对于远程登录的用户特别有用——即使网络连接中断,用户也不会失去对已经打开的命令行会话的控制。只要再次登录到远程主机上执行screen -r就可以恢复会话的运行。
打在命令号里的称为Screen命令,如果要向Screen窗口管理器发送命令,则需要先按住Ctrl+a。如Ctrl+a d是断开当前screen会话。
screen 新建一个会话,开始干活。(1小时以后)累了,想出去遛遛:
Ctrl+a d 断开(detach)当前会话 电脑一盖,断开ssh连接,出门喽~(半小时以后)回来了,重新ssh上服务器:
screen -ls 列出所有会话 看看刚才断开的那个会话的id是什么
screen -r id 重新(attach)连上会话 继续工作~
screen -S name 以name为名字新建一个会话,之后可以通过名字或id来进行重连,比较方便
kill id杀掉一个会话,接着screen -wipe 把被杀掉的会话从列表中清除
更全的命令列表

tmux的使用

Tmux 使用教程

VSCode的使用

让VS Code在服务器上做开发
用VS Code连接到服务器上的容器:本地安装Remote - Container插件;服务器上在docker run的时候添加参数-v ~/.vscode-server:/root/.vscode-server就可以了,这样里外共用一套插件,也不用每次新开容器的时候又要安装一遍,参考链接
VSCode 如何使用 Python 的虚拟环境
VSCode Linux版的快捷键速查表
VSCode 安装配置 yapf
pylint是静态检查,在用第三方库的时候有些成员只有在运行代码的时候才会被建立,它就找不到成员,会报错Module ‘xx’ has no ‘xx’ member pylint(no-member)。解决方法是,在settings.json中加上一句:

"python.linting.pylintArgs": [
    "--errors-only",
    "--generated-members=numpy.* ,torch.* ,cv2.*, cv.*"
]

VSCode的TIMELINE可以对比同一个文件在时间的变迁中(也即git的不同版本)每次迭代发生的变化,相当舒服,用了这么久才发现有这个功能
如果不加"--errors-only",pylint将对各种不符合pep8规范的写法进行提示(例如逗号后面没有空格,一行语句最后面多出了空格)。如果没有"python.linting.pylintArgs"参数,似乎默认是不对其进行提示的。原文请戳这里(dscarmo的回答)
在代码中用sys.path.append()添加了查找路径之后,pylint报错找不到这些包的解决方案:vscode中PyLint报错Unable to import解决方案
在项目目录下建立一个.pylintrc文件可以自定义该项目的pylint配置
用VsCode写C++时提示无法打开源文件"xx.h":缺哪个文件就用everything搜到对应的目录然后添加到c_cpp_properties.json文件的includePath变量下
VSCode提示错误:"cout"不明确
有时候有些缓存文件夹比如__pycache__,我们不会去点开但它一直在那占着位置,影响工作,可以把它隐藏起来:vscode中设置工作区隐藏文件或文件夹
vscode中用正则表达式给键值对快速添加引号
VSCode修改代码格式化工具的配置:
打开设置,搜索provider,可以选择用哪一款格式化工具,这里选择yapf;搜索yapfargs,可以给yapf自定义配置一些参数,比如--style={column_limit: 100}注意不要加"",直接把内容写进去就行,不然会识别错误的
有时候需要在一个VSCode窗口打开两个不同位置的目录,点击上方 文件——将文件夹添加到工作区 就可以啦~
VSCode突然登录不上,尽管密码是对的,可能是因为某种缘故,~/.vscode-server目录下部分子目录的权限被修改(例如启动容器的时候-v了宿主机的~/.vscode-server目录,容器又直接用的root用户,然后在用VSCode访问容器的时候装了新的插件,此时新插件子目录的权限就变成root,而不是宿主机上的某个用户了),可尝试sudo chown -R username ~/.vscode-server,一般就可以解决问题了。

VSCode-Server用着用着有些插件就死活开不起来的解决方案
提示信息形如“无法激活 “isort” 扩展, 因为它依赖于未加载的 “Python” 扩展。是否要重新加载窗口以加载扩展名?”
但重新加载窗口是没有用的,直接安装另一个版本的插件立马复活,参考链接

VSCode-Server用了一段时间之后各种卡的解决方案
在git一栏点开一个文件要转好几秒钟,进行一次git操作要好几秒钟,做什么事情都要多一个好几秒钟的延时,鼠标移过去也不会显示超链接啥的,非常龟速,非常难受。
看了一下~/.vscode-server/data/User/workspaceStorage/ 目录,足足有40G,直接一把删掉,重启VSCode,欧了,啥啥都快了,超链接也有了。

VSCode-Server老是自动下载新版本的解决方案
VSCode经常自己更新版本,客户端更新之后,VSCode-Server需要保持与客户端一致的版本,所以它也会更新,但是服务器上下载VSCode-Server很慢,而VSCode发布又很频繁,那么差不多每个月都会有一次这种经历,就非常蛋疼。解决这个问题的办法是,取消客户端的自动更新,同时保持连接上远程的不同客户端的版本一致。
原因说明;查看VSCode当前版本;取消客户端的自动更新;将VSCode降级为旧版本

Visual Studio的使用

VS把相同变量设置成高亮

在非Root的情况下安装各种东西

深度好文
非root权限安装pip、其他包
非root用户安装Python3.6
他们都是用的wget,那可能就是说明apt-get install需要sudo,而wget不需要吧

Windows一些生僻的知识点

Windows上的bash密码忘记了怎么办:
首先输入 lxrun /setdefaultuser root ,把root设置为默认的用户;
然后输入 bash,此时以root身份进入linux bash;
接着输入passwd 用户名,修改某个用户的sudo密码,搞定。
最后输入lxrun /setdefaultuser 用户名,把默认用户改回来。

删除文件时提示文件被占用的解决办法:任务管理器——上方“性能”——下方“打开资源监视器”——CPU——关联的句柄,输入被占用的文件名按回车,就可以看到是什么程序在占用它,把对应的程序(进程)结束掉之后就可以删除该文件了。如果是explorer.exe也就是文件资源管理器占用的,结束进程之后文件资源管理器就没了,电脑下面一栏就没了,需要重新打开:任务管理器——上方“文件”——运行新任务,输入explorer.exe按回车,就恢复了。
也可以下载一个小软件Unlocker来解除文件占用,方便快捷。

电脑的卸载或更改程序出问题了,打不开一直闪退,尝试用命令行卸载

清除历史凭据:在某个地方输入过一次账号密码之后,想切换账号发现每次都自动登录进去,没法切换账号,这是需要在设置中搜索“凭据”,选择"管理 Windows 凭据",把需要修改的凭据重新编辑或直接删除即可,参考链接

硬盘莫名其妙变成动态磁盘,磁盘管理显示“动态 无效”,需要用WinHex软件修改MBR分区中的对应位置,把动态对应的42改成需要的格式,如07 NTFS,83 ext3/ext4,文件系统类型与数字对应表看这里,使用WinHex具体操作方式看这里。

Windows不支持打开ext4格式的文件,要想打开需要安装DiskGenius软件,它既可以做磁盘分区、格式化,又可以提供支持多文件系统格式的文件读取与复制。

至于如何把SATA硬盘插到主板上,看这里。

自定义右键菜单: 修改注册表 教程1 教程2
做出类似“git bash here”的右键菜单选项:
Win+R,运行regedit,在HKEY_CLASSES_ROOT\Directory\Background\shell目录下建立一个文件夹(在注册表编辑器中称为“项”),建好后会自带一个名称为 (默认) 的项,它就是我们打开右键菜单时,会看到的提示文本。新建一个名称为 Icon 的项,其值可以设为我们需要的exe文件的完整路径,若如此做,右键菜单对应行的图标将变成这个exe文件所对应的图标。接着在刚才新建的目录下面再建一个文件夹(项),重命名为command。把默认值改为我们要运行的程序,例如git bash对应的是"d:\Program Files\Git\git-bash.exe" "--cd=%v.",Cmder对应的是"D:\cmder\Cmder.exe",然后就大功告成啦!

更自动化点的操作:用批处理代码增删改查注册表
reg query查询某个键值,文档在此
reg add添加某个键值,文档在此
数值型用REG_DWORD类型,字符用REG_SZ类型
reg命令需要注意的是目录最后不能有\,否则会报错"系统找不到指定的注册表项或值"。如果目录名中包含空格则需要用双引号括起来,否则会报错"无效语法"或者"无效项名"
例子:

# 查询某个具体项的值
reg query HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\"Windows NT"\CurrentVersion\Winlogon /v LegalNoticeCaption
# 查询整个目录下的项
reg query HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\"Windows NT"\CurrentVersion\Winlogon
# 在指定目录下添加一个名为test的项,值为abc
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\"Windows NT"\CurrentVersion\Winlogon /v test /t REG_SZ /d abc
# 对一个已有项进行add将提示是否覆盖,也即add具有增改双重功能
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\"Windows NT"\CurrentVersion\Winlogon /v test /t REG_SZ /d abcd
# 我们不希望自动化脚本弹出提示,所以加个/f参数直接确认操作,也即直接覆盖
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\"Windows NT"\CurrentVersion\Winlogon /v test /t REG_SZ /d abcd /f

不知道为啥, 在bat文件里直接写reg命令一直提示无效语法,搜了半天换成下面这个语句就可以了:
cmd /k reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v test /t REG_SZ /d abcd /f
但是cmd /k运行结束后整个bat就退出了,不符合我们的要求,所以后面改成把命令写在for语句里头了

查看端口占用,类似lsof -i:pid的命令:netstat -aon|findstr "pid"
查看进程信息,类似ps -aux | grep pid的命令:tasklist|findstr "pid"

开机自动运行批处理脚本文件
这个方法是在欢迎界面之后,进入桌面了才启动脚本文件,不符合我们的需求,我们要的是WINDOWS登录系统之前(欢迎界面)运行指定程序脚本服务
批处理之for命令,处理文本好工具:基本用法 复杂一点的操作
for也可以用于使用将其他命令的输出作为输入来分析,也即接收命令的输出结果(原文链接):

for /f "delims=" %%i in ('dir') do (
echo %%i
)

如果我们想获取文本文件中某一行的内容然后跳出循环,可以使用goto语句(原文链接):

for /f "skip=10" %%L in (test.txt) do (
set text=%%L
goto:endfor
)
:endfor
# 其他内容

批处理之生成随机数random
批处理之获取日期date时间time
批处理中==号用于判断相等,判断语句if的写法为:

if %today%==24 (
set file=anniversary.txt
) else (
set file=daily.txt
)

批处理代码在移植到另一台电脑的时候遇到了两个问题:一个是teamviewer远程拉过去的文件自动变成utf-8编码,我们需要手动改回ANSI编码,否则中文会乱码;一个是reg add命令报错“无效访问”,搞了半天都不行,最后是通过右击注册表的子目录,修改了权限,把所有用户的权限都开到最大,就可以正常修改了。

在笔记本用Cmder进行ssh时报错:Bad owner or permissions on .ssh/config,解决方案在此

Vscode: 关闭pylint的某些报错

将图片转成eps文件(Windows和Linux下应该都能用):
sam2p foo.png foo.eps 或者 bmeps -c foo.png foo.eps

使用IDM时在Chrome上打开pdf文件会自动下载,无法预览,这时需要在IDM主页的 下载——选项——文件类型 中把PDF删掉,使IDM不会先于Chrome截获pdf文件,参考链接

WinSCP传输文件到另一台机子上报错:SSH2_MSG_CHANNEL_FAILURE for nonexistent channel 0,一般是传输目标磁盘满了,清理之后断点续传即可(参考链接)。

LaTeX语法

为了支持中文, 我们可以使用这个: \documentclass[UTF8]{ctexart}

别人的LaTeX大全
Latex之安装宏包
latex两栏排版时如何插入跨栏的表格或图形{汇总}
latex题注(caption)位置
Latex调整表格与题注之间的间距
LaTeX文档插入图片的几种常用方法
LaTeX算法排版例子
LaTex中把下标置于文本正下方的方法
各种常用盒子介绍

表格Table
Latex基本表格绘制(很有用!)
一个在线生成LaTeX表格命令的工具
设置表格的宽度和高度
表格以 \begin{tabular}{|c|c|c|c|c|c|c|}开头,字母的个数对应列数,|代表列竖线,字母可以有三种,l代表左对齐,c代表居中,r代表右对齐
外面可以再套一层 \begin{table}来控制一些格式
\multicolumn命令不需要导入包, 但\multirow命令需要导入multirow包
multirow{2}{*}{text} 第一个参数表示合并2行,*表示由系统自动调整文字,text表示要写入的文字
multicolumn{2}{|c|}{text} 表示跨2列,采用中心对齐的方式,text是要写入的文字
\hline 表示画出一整条从左至右横线
\cline{2-3} 表示画出一条在第2栏位到第3栏位的横线段,其他栏位将不会有横线段
设置整个表格的行高:\renewcommand\arraystretch{0}
设置表格某一行的行高:\specialrule{0pt}{5pt}{5pt} 第一个参数表示横线宽,0表示透明,第二个参数表示距离上面内容的距离,第三个参数表示距离下面内容的距离
设置表格的列宽:把c换成p{0.8cm},此时为左对齐,如果还需要居中,则写成p{0.8cm}<{\centering},右对齐是p{0.8cm}<{\raggedright},参考链接
在表格换行符\\后添加[3pt]可以方便地控制某一行的行高

LaTeX计算写了多少字:texcount thesis.tex -inc -ch-only File(s) total 的Words in text一项中
LaTeX的图表是比较灵活的,它会自动找空位填充,而且每页貌似只会出现一张图。有时候我们把figure的代码放在两段文本中间,但往往发现编译出来的图片“跑了”。LaTeX有强制限定位置的选项,我们有办法让它乖乖呆在我们想让它待着的位置:

\begin{figure}
	\centering
	\includegraphics[width=0.7\linewidth]{figure/somefig}
	\caption{某示意图}
	\label{fig:somefig}
\end{figure}

只要加上一个[h]选项,就能强制固定位置啦~

\begin{figure}[h]
	\centering
	\includegraphics[width=0.7\linewidth]{figure/somefig}
	\caption{某示意图}
	\label{fig:somefig}
\end{figure}

如果用了双栏的模板,但是图或者表太大了想以单栏的形式放在中间,只需要把\begin{figure} ... \end{figure}改成\begin{figure*} ... \end{figure*},表table也是这样。

LaTeX多行注释:

\iffalse
注释内容
\fi

设置图与图标题之间的距离:

\setlength{\abovecaptionskip}{0.cm}
\setlength{\belowcaptionskip}{-0.cm}
\caption{balabala}
% 注意set语句要在caption之前,否则没有效果

有时候两个图中间,或者图跟下面的段落之间有很大的间距,可以尝试添加一行语句(要添加在figure环境里面,放外面可能会影响到其他的地方):

\vspace{-0.3cm}
\includegraphics[balabala]

并排放置的两个图可以调整水平间距:

\includegraphics[left]
\hspace{-0.3cm}
\includegraphics[right]

多个图共用一个标题可以使用子图命令:

\subfigure[Webcam to Dslr]{
	\label{Fig.w2d}
	\includegraphics[width=0.5\textwidth]{figures/office31/webcam2dslr_epoch19.jpg}
	\includegraphics[width=0.5\textwidth]{figures/office31/webcam2dslr_epoch99.jpg}
}

有时候子图过多一页放不下,想换页,但是一个figure标签只能在一页里面,超出部分就显示不出来了,用两个figure标签一般情况下又会变成两个图,有各自的标题并且子图重新编号了,这个时候我们就需要一个骚操作:

\begin{figure} 
  \subfigure[Fisrt Part1]{% balabala}
  \subfigure[Fisrt Part2]{% balabala}
\end{figure}
\addtocounter{figure}{-1}       %关键一步,一般在end figure之后,LaTeX的图形计数器就会自增1,
% 比如前面是图1后面就会是图2,我们这里将图形计数器的计数-1,也就是接下来的这个图它还是图1,也就是有两个图1,
% 也就变成了一个图!
\begin{figure} 
  \subfigure[Second Part1]{balabala}
  \subfigure[Second Part2]{balabala}   
  \caption{balabala} % 注意总的标题放在最后一个figure标签中,然后前面的figure中不要写caption语句。
  % 如果前面有caption,就会被分成两个图,且题注都是图1
\end{figure}

\setlength{\textfloatsep}{12pt}可以控制图表与文字之间的距离,可以靠微调这个距离来调节图与文字之间的距离,轻微超页就调小,不够就调大

给表格加题注的时候发现了一个现象,如果把\label放在tabular之前,那么拿到的是对这个小节subsection的引用,而放在tabular之后(就像下面的代码)才能得到对表的引用,略神奇

\begin{table}
	\centering
	\begin{tabular}{l|cc}
		% content
	\end{tabular}
	\caption{xxx}
	\label{xxx}
\end{table}

后记:貌似加了counter反而有问题,只要前面的figure不加caption,图形计数器就不会自增(因为图1第一页的图没有题注,所以从前面的图0到这里的图1在逻辑上是没有问题的)

多对象排版minipage
minipage可以用来排版各种格式的对象组合,不管是图片、表格还是算法,统统可以包进来。

目前在用的都是两层嵌套,去掉外面的一层会报错,不懂个中原因:

\begin{minipage}{\textwidth}
	\begin{minipage}[t]{0.3\textwidth}
	\makeatletter\def\@captype{table}\makeatother
		# 表格1的内容
		\begin{tabular}
		xxx
		\end{tabular}
	\end{minipage}
	# 表格1跟图片2中间没有隔着空行,它们将排版在同一行
	\begin{minipage}[t]{0.3\textwidth}
	\makeatletter\def\@captype{figure}\makeatother	
		# 图片2的内容
		\subfigure xxx	
	\end{minipage}
	
	# 图片2跟算法3中间隔着一行空行,它们将排版在不同行
	\begin{minipage}[t]{0.3\textwidth}
	\makeatletter\def\@captype{algorithm}\makeatother	
		# 算法3的内容
	\end{minipage}	
\end{minipage}

放置图表的时候,table跟figure环境被内层minipage所取代,也即不再需要\begin{table}\begin{figure},但题注的标号顺序不能乱,所以要加上一行这样的命令:
\makeatletter\def\@captype{table}\makeatother,来保持正确的标号
另外,子minipage之间如果没有隔着空行,就会放置在文档的同一行,如果有就会换行。上图的表格1跟图片2会排版在同一行,算法3在下一行
并排后发现它们的顶端没有对齐,minipage顶部对齐

\ref{}引用图片没有超链接:可能是忘记引用包了,要加上这个\usepackage{hyperref}

添加行号:

% 单栏添加行号
\usepackage{lineno}
\linenumbers % 在该语句之后的行都会有行号(公式无行号)
\nolinenumbers % 在该语句之后的行不再有行号
% 双栏添加行号
\usepackage[switch]{lineno}
\linenumbers 

查看两个tex文件的差异,可用于校对修改后的论文,看哪些地方被改过了,怎么改的:
latexdiff original.tex revised.tex > diff.tex,然后compile diff.tex

cvpr2021模板的一些用法:
正文直接用那个模板就可以了,要写补充材料的话,在\maketitle的前面加上一句\appendix即可,它会将1.Method, 2.Experiments转变成A.Method, B.Experiments
公式标签的默认格式是(编号),例如(1), (2),如果想要显示(1.1), (A.1),也即带上本节的节编号,那么需要在tex文件开头加上一句\numberwithin{equation}{section}
如果双栏不好看想用单栏,则在cvpr.cls文件中将\LoadClass[10pt,twocolumn,letterpaper]{article}中的twocolumn改成onecolumn即可。
为了跟正文的表格区分开,不致使读者误以为我们说的Table 1是正文的表1,我们要给补充材料的表格加一个前缀:\renewcommand{\thetable}{A\arabic{table}},图也是类似:\renewcommand{\thefigure}{A\arabic{figure}}

equation中不能有空行
equation*就可以不给公式加编号
LaTeX中左右引号有别,左是`右是’:

`单引号'  ``双引号''

调用一些函数比如includegraphics时,必需参数放花括号,非必需参数放方括号
&常用于分栏(公式align*、表格tabular),\\常用于换行
\tableofcontents 命令可自动提取\section中的信息并生成目录
标题、作者等信息直到\maketitle命令才编译进文档,在此之前的\title\author等只是设定标题、作者字段的值,并没有把它们放进文档中(可以看到它们的位置是在\begin{document}之外)

疑难杂症
Undefined control sequence: 可能是关键字拼写错误或大小写错误,如\For写成了\FOR。参考链接
删除了文献的引用之后,编译出来的References仍能看到一堆文献:把.aux, .bbl, .blg, .brf, .log, .syntex.gz文件都删掉,然后重新编译,就能成功更新了

VirtualBox

Ubuntu下安装Windows虚拟机
启动时遇到问题VT-x is disabled in the BIOS for both all CPU modes (VERR_VMX_MSR_ALL_VMX_DISABLED):
解决方案:进入BIOS,在CPU设置中把Intel® Virtualization Technology选为Enabled;然后在VirtualBox的设置——系统——处理器中把PAE/NX选项勾上
创建共享文件夹

VMware

下载链接
用U盘装机(我用这个就够用了)
用U盘装机plus版
若找不到U盘则需要运行services.msc,重启VMware USB Arbitration Service服务,然后重新插U盘,重新启动VMware,就可以了。参考链接
在主机与虚拟机之间切换U盘
在"虚拟机"选项卡安装了VMware Tools之后,就可以在虚拟机和主机之间传输文件了~
虚拟机中访问主机硬盘文件的方法——共享文件夹,参考链接
虚拟机不能直接打开iso文件来安装东西,需要在设置里面挂载iso文件,参考链接

安装后第一次启动虚拟机报错:“VMware Workstation Pro 启动虚拟机报错,您的主机不满足在启用 Hyper-V 或 Device/Credential Guard 的情况下运行 VMware Workstation 的最低要求”,需要把这两个服务关掉,首先打开面板,点击程序——启用或关闭Windows功能,把Hyper-V和Windows虚拟机监控程序平台的勾去掉,再以管理员身份运行Windows Powershell,执行bcdedit /set hypervisorlaunchtype off,然后重启电脑,再启动虚拟机就正常了。参考链接

想让虚拟机能访问与本机在同个局域网内的机子,要使用桥接模式,并选用主机的网卡,具体操作见此链接。到它说的第9步之后,在虚拟机里ifconfig就可以看到ip已经变到跟本机同一个网段了,就已经可以正常访问同个局域网内的机子了。

虚拟机与主机共享文件与剪贴板:需要安装VMTools,一般在首页选中虚拟机实例后点击安装。有时候安装选项是灰色的,试了一下网上说的改软盘连接方式不行,那就手动安装一下,首先去官网下载安装包,以zip包为例,unzip解压后进入vmtools目录,双击linux.iso文件,把里面的vmware-tools-distrib目录解压出来,然后进入这个目录,在终端里运行sudo ./vmware-install.pl,一通回车过后就安装成功了~(参考链接1,参考链接2)
接下来是配置共享文件夹,右键虚拟机实例,设置——选项——共享文件夹,选总是启用,然后添加一个共享文件夹,主机路径就是外面的实际路径,名称填一个目录名就可以了,不需要填绝对路径。设置完了重启一下,就会在/mnt/hgfs目录下出现对应的目录,共享文件夹的配置就完成啦((参考链接)!

Qt

安装Qt
When executing step qmake

运维

本小节基于Ubuntu18.04.6 LTS版本。
下面一切操作都是借助IPMI,如果没有IPMI,ssh或者网络出点什么问题基本就寄了,人不在服务器旁边就啥都做不了了。

系统重装
重启之后df -h发现数据盘不见了!不慌,顶多没挂上,数据不会丢,先看ll /dev/sd*看看盘在不在,在就只是没挂载,手动挂一下就好了。再看一下ll /mnt/sd*,一般是有这个目录的,只是不知道为什么它没挂上去。然后mount /dev/sda /mnt/sda -v挂载上去,-v可以显示详细信息,方便排错。如果挂载完/mnt/sda里有东西了,就算是挂载成功了,问题解决。

重启之后ssh连不上了,systemctl status sshd显示"inactive (dead)",是不是服务器崩了!不慌,先看看日志里有没有什么信息:journalctl -u sshd | tail -n 10再看看sshd命令自己有没有说为啥开不起来:sshd -t,最后重启一下ssh服务:/etc/init.d/ssh start,status变为"active (running)"就大功告成了!(参考链接1,参考链接2,参考链接3)

搞来搞去还是有问题,还不如直接重装呢,IPMI都提供了远程加载iso镜像文件作为安装盘的功能了,把数据备份好一波重装就完事了

/etc/shadow里字段的解释
/etc/passwd各字段含义

日常运维
top命令VIRT,RES,SHR,DATA的含义
top命令各项输出信息含义
top -H -p pid可以查看进程下面的线程
理解top命令里面的load average

htoptop要更高级,显示的内容更多,参考链接

给服务器配置静态网络:
前提:人在服务器旁;有权限访问路由器后台。
一般最开始还是要通过键盘显示器线下直连服务器来操作,除非服务器一买回来就预装了IPMI且知道IPMI对应的IP和账号密码,才能从线上连接到服务器。

服务器IP配置(参考链接):

# 先看一下网卡名称
ifconfig
# 在路由器配置DHCP静态表
# 重启网卡,路由就会根据新规则重新给eth0网卡分配ip
sudo ifconfig eth0 down && sudo ifconfig eth0 up
# 对于静态ip,需要设置ip和掩码,eth0是上一步查到的网卡名,根据实际情况修改
# ifconfig eth0 192.168.1.4 netmask 255.255.255.0

上文"在路由器配置DHCP静态表"的具体操作如下(以H3C GR2200路由器为例):进入首页,点击左侧“接口管理”——“DHCP设置”——去到路由器控制页,找到"DHCP静态表",新建一个条目,把ifconfig查出来的mac地址和想分配给它的ip地址写进来,然后点击页面上方的"DHCP客户列表",把目前占用这个地址的用户释放掉(这个用户需要重连网络才能重新获得一个可用的ip),然后去到首页左侧"安全专区"——“ARP安全”,搜一下这个ip下有没有条目,有的话就删掉,至此路由器端的配置就完成了,无需重启路由器即可应用更新。

IPMI的IP配置:
为了跟路由器配合,我们配置成自动获取IP,同时在这里也展示静态配置方式。

# 安装ipmitool。跑IPMI的地方好像是固件,ipmitools是工具包,
# 在没有这个工具包的时候也能运行IPMI,也能进界面,只是没有办法重新配置而已
sudo apt install -y ipmitool
# 使用ipmitool查询当前IPMI信息,1是序号
sudo ipmitool lan print 1

############### IP配置方式一:自动获取IP ###############
# 设置IPMI为DHCP
sudo ipmitool lan set 1 ipsrc dhcp
# 查询IPMI用户
sudo ipmitool user list 1
# 修改用户名/新建用户,2表示前面list出来的序号为2的用户,下文记为<user id>
sudo ipmitool user set name 2 <username>
# 修改用户密码,2表示前面list出来的序号为2的用户
sudo ipmitool user set password <user id> <passwd>

############### IP配置方式二:静态IP ###############
# 设置IPMI为静态获取IP
sudo ipmitool lan set 1 ipsrc static
# 修改IPMI静态IP地址
sudo ipmitool lan set 1 ipaddr 192.168.3.123
# 修改子网掩码
sudo ipmitool lan set 1 netmask 255.255.255.0
# 修改默认网关
sudo ipmitool lan set 1 defgw ipaddr 192.168.3.1

改完IPMI登录密码需要重启服务器才能生效。

不管是服务器网卡还是IPMI的网卡,在设置时都需要先改路由器的配置,再去改服务器的配置,比如先配好DHCP静态IP,删除ARP表里原有的项,再将IPMI设置为DHCP,则IPMI的ip会立即刷新。

修改主机名,让多台服务器井井有条:
PS:安装完systemd之后会自动重启网卡,如果ip没有绑定,服务器的ip会变,因此必须先配置好网络再来搞主机名。

sudo apt install systemd
# 查看一些详细信息
hostnamectl
# 修改主机名
hostnamectl set-hostname <hostname>

下次登录主机名就会变成新的。

OneNote用久了之后随便点几下就会卡住闪退,解决方案:
在everything中搜索"Microsoft\OneNote",并进入目录;
把目录"16.0"重命名为其他名字;
启动OneNote,它会重新构建缓存。如果提示未登录,需要先进行登录,否则拉不下来云服务器上的内容。
然后就大功告成啦!

服务启动失败时,查看服务的日志:journalctl -u <service-name>

python与blender的结合
blender用于生成3D渲染图片,结合python可以运用代码行灵活方便地进行图像渲染生成。

自己编译第三方库
有些库没办法直接pip install到,需要我们自己下载源码下来编译。有的是make && make install,有的是python setup.py install。在编译的时候可能会报错找不到某些文件,比如 fatal error: maskApi.h: No such file or directory。这是因为没有安装cython,用pip安装一个就可以了(原文链接)。如果报找不到Python.h,可能要安装python-dev,但其实大多数时候我们硬盘里面是有这个文件的,只是setup.py找不到,我们只需要帮它找到,然后把路径写进环境变量就行了。locate Python.h会在整个硬盘里面寻找这个文件,找到对应的路径之后,我们把这个路径加入CPATH环境变量,写入.bashrc中:export CPATH="$CPATH:xxxxx",再source一下就可以啦!

疑难杂症
在linux命令行中键入nvidia-smi,显示没有进程但是GPU显存却使用很多:(参考链接1,参考链接2)
网上大多教的是sudo fuser -v /dev/nvidia0,但网上教程不曾提及的一点是该命令会把正常运行中占用任意显卡的进程显示到每一张卡上,因此对0卡fuser看到的是0-7卡的正常进程和0卡的僵尸进程,并不是所有显示的结果都是僵尸进程。我们需要再对一张正常的卡使用fuser,对比两者输出的差异,就能得到0卡僵尸进程的列表了。为了确保万无一失,我们需要把输出的pid拎出来用ps仔细看看,确认无误后再进行kill:

sudo fuser -v /dev/nvidia0 |awk '{for(i=1;i<=NF;i++) print $i;}' | xargs -n 1 ps -f

有时候会看到父进程为类似/usr/bin/containerd-shim-runc-v2 -namespace moby -id xxx -address /run/containerd/containerd.sock的程序,子进程看起来像是挂掉了,这是是docker容器的进程,不能杀,杀了别人的docker容器就直接被stop了。

nvidia-smi很慢,而且空载耗电100W:需要修改它的运行模式:sudo nvidia-persistenced --persistence-mode,参考链接
服务器重启之后nvidia-smi用不了,报“NVIDIA-SMI has failed because it couldn’t communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running”:驱动还在,但好像掉了,需要重新启动一下,参考链接
systemctl restart xx.services以及其他systemctl相关操作时,报错"Failed to add /run/systemd/ask-password to directory watch: No space left on device",sudo systemd-analyze verify xx.service时报错"Failed to acquire watch file descriptor: No space left on device":处理方法见下面代码,参考链接

# 查看当前的配置,默认值是8192
cat /proc/sys/fs/inotify/max_user_watches
# 临时更改,重启后会失效
sudo sysctl fs.inotify.max_user_watches=1048576
# 永久更改,在文件后面添加一句 fs.inotify.max_user_watches=1048576
sudo vim /etc/sysctl.conf

本文标签: 使用方法命令Linux