0.linux笔记.....持续更新...
@Author:ZhuHongzhao0.0. VScode几点基本用法0.1. 将UbuntuLauncher启动器移动到底部0.2. 一个窗口中运行多个终端方法1.Markdown的用法2.source 用法3.安装软件4.Linux cat命令详解6.服务器会话问题7.安装NVIDIA显卡驱动+cuda+cudnn步骤8.Linux添加打印机10.git和仓库基本操作...
24.使用终端或vim时,不能输入(和卡死了一样)时的解决方法:ctrl + q
105.将自己的ubuntu电脑设置为一台可远程ssh访问的服务器
106.在ubuntu电脑(或服务器)登录另一台ubuntu电脑(或服务器)的文件系统ftp、sftp
114.当前运行的docker修改环境后,想在本地保存下来的方法
122.LD_LIBRARY_PATH详解、C++静态库与动态库
0. 各种小tips
VScode几点基本用法
部分参考http://www.cnblogs.com/bloglkl/p/5797805.html
(1) 在visual studio code中插件下载Markdown Preview Github Styling即可使用markdown.
(2) vscode 安装code runner插件可以运行代码
(3) vscode 安装"C++"插件和"Python"插件可以在代码中选中函数后实现 查看定义、转到定义 的功能
(4) 切换中文环境:先安装Chinese插件,然后ctrl+shift+p组合键,搜索configure display language,选择zh-cn,可以改成中文环境
(5) 安装vscode-icons插件可以使VScode左侧的资源管理器根据文件类型显示图标
(6) 更新 vscode
wget https://vscode-update.azurewebsites.net/latest/linux-deb-x64/stable -O /tmp/code_latest_amd64.deb
sudo dpkg -i /tmp/code_latest_amd64.deb
(7) 快捷键
alt + o 在.cc和.h文件之间切换
ctrl + alt - 回到上一次位置
Ctrl + . 快速修复部分可以修复的语法错误
ctrl + p 搜索文件
ctrl + f 本文件下搜索关键字
ctrl + shift + f 全局搜索关键字在所有文件中位置
Ctrl + Shift + i 对代码进行谷歌风格标准化
ctrl + shift + b 运行任务
Ctrl + Shift + P 展示全局命令面板,去掉>后也可以搜索文件,相当于ctrl + p
Ctrl + Shift + K 删除行
Ctrl + Shift + 上下左右箭头 选中文本的前n列进行操作
alt + Shift + 上下左右箭头 选中文本的前n列进行操作(同上)
0.1 将UbuntuLauncher启动器移动到底部
(1) ubuntu16.04以后可以在终端使用
gsettings set com.canonical.Unity.Launcher launcher-position Bottom
将Launcher启动器移动到底部。
(2) 使用
gsettings set com.canonical.Unity.Launcher launcher-position Left
可以重新将Launcher启动器移动到左侧。
0.2 一个窗口中运行多个终端方法
ctrl+shift+t即可
注意:ctrl+shift+t是在一个窗口中再打开一个终端
ctrl+alt+t是打开一个新终端窗口
1. Markdown的用法
参考https://www.jianshu.com/p/de9c98bba332
(1)在markdown中正确显示数学公式
Vistual Studio Code天生支持Markdown编译,文件后缀为md即可,但是不支持数学公式,其实在文件开头加上以下代码即可,会自动获得MathJax的脚本支持。MathJax语法可以自己去官网学习。
<script type="text/javascript"
src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
注意: 在vs code中的插件转pdf的时候公式不生效,这时候建议转为html,再用了浏览器把html转为pdf,如果pdf有乱码,可以用nodepad++将html的编码改为utf-8后再转pdf。
摘自:https://blog.csdn.net/ancewer/article/details/73279127
(2)实现页面内跳转
参考https://www.cnblogs.com/JohnTsai/p/4027229.html,其中还有另一种方法,我没记录下来。
一. 把标题写在文章最前面:
使用markdown语法:中括号内写内容,一般是后文中要跳转到的标题,后面加上括号,括号内必须加一个#,否则会跳转出页面,#后是id
[点击跳转](#jump)
二.把正文标题写成如下的形式:
定义一个锚(id):这个id必须在后面有对应
<span id="jump">跳转到的地方</span>
2. source 用法
source的作用就是把一个文件的内容当成是shell来执行。
可以新建一个文本文件a,(一般写成a.sh表示shell文件,不这么写也行,因为后缀名只是标识而已),然后在该文件中写入一系列指令,如:
cd desktop
cd Work-progress
gedit Readme.md
然后在该文件目录下使用如下命令,就依次执行了a文件中的这三个命令。
source a
shell编程中的命令有时和C语言是一样的。&&表示与,||表示或。把两个命令用&&联接起来,如 make mrproper && make menuconfig,表示要第一个命令执行成功才能执行第二个命令。对执行顺序有要求的命令能保证一旦有错误发生,下面的命令不会盲目地继续执行。
source命令(从 C Shell 而来)是bash shell的内置命令。点命令,就是一个点符号,(从Bourne Shell而来)是source的另一名称。
这两个命令都以一个脚本为参数,该脚本将作为当前shell的环境执行,即不会启动一个新的子进程。所有在脚本中设置的变量将成为当前Shell的一部分。
Linux source命令:
https://blog.csdn.net/qq_39759656/article/details/83547582
通常用法:source filepath 或 . filepath
功能:使当前shell读入路径为filepath的shell文件并依次执行文件中的所有语句,通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。例如,当我们修改了/etc/profile文件,并想让它立刻生效,而不用重新登录,就可以使用source命令,如source /etc/profile。
source命令(从 C Shell 而来)是bash shell的内置命令;点命令(.),就是个点符号(从Bourne Shell而来)是source的另一名称。这从用法中也能看出来。
source filepath 与 sh filepath 、./filepath的区别:
当shell脚本具有可执行权限时,用sh filepath与./filepath是没有区别的。./filepath是因为当前目录没有在PATH中,所有"."是用来表示当前目录的。
sh filepath 会重新建立一个子shell,在子shell中执行脚本里面的语句,该子shell继承父shell的环境变量,但子shell是新建的,其改变的变量不会被带回父shell,除非使用export。
source filename其实只是简单地读取脚本里面的语句依次在当前shell里面执行,没有建立新的子shell。那么脚本里面所有新建、改变变量的语句都会保存在当前shell里面。
举例说明:
新建一个test.sh脚本,内容为:A=1;
修改其可执行权限:chmod +x test.sh;
运行sh test.sh后,echo $A,显示为空,因为A=1并未传回给当前shell;
运行./test.sh后,也是一样的效果;
运行source test.sh 或者 . test.sh,然后echo $A,则会显示1,说明A=1的变量在当前shell中;
3. dpkg、apt安装卸载软件
sudo dpkg -i XXX.deb # 安装本地软件包(.deb文件),需要先下载下来.deb文件
dpkg -l #查看dpkg方式安装了哪些软件
sudo dpkg -purge XXX #卸载dpkg软件,通过dpkg -l查看软件叫什么,不需要加.deb
dpkg -P #同上,彻底卸载,包括配置文件等。
dpkg -r #卸载,不包括配置文件
sudo apt-get install XXX # XXX(无后缀名)是直接从网络服务器上来安装软件包
apt-get --purge remove <package> # 删除软件及其配置文件
apt-get autoremove <package> # 删除没用的依赖包
sudo apt update # 更新软件
sudo apt-get update # 更新软件
sudo apt upgrade # 更新软件
sudo apt-get upgrade # 更新软件
4. Linux cat命令详解
cat命令是linux下的一个文本输出命令,通常是用于观看某个文件的内容的;
cat主要有三大功能:
1.一次显示整个文件
cat filename
2.从键盘创建一个文件,它只能创建新文件,不能编辑已有文件, 编辑文件可以用gedit或vim.
cat >filename
3.将几个文件合并为一个文件
$cat file >file
$cat file1 file2 >file
这里可以直接把一个文件输入到另一个文件中,也可以把两个文件连接后输入到第三个个文件中,但是最后一个文件名前必须加 >,即新创建一个文件。
说明:把档案串连接后传到基本输出(屏幕或加 > fileName 到另一个档案)
参数:
-n 或 –number 由 1 开始对所有输出的行数编号
-b 或 –number-nonblank 和 -n 相似,只不过对于空白行不编号
-s 或 –squeeze-blank 当遇到有连续两行以上的空白行,就代换为一行的空白行
-v 或 –show-nonprinting
范例:
cat -n linuxfile1 > linuxfile2
把 linuxfile1 的档案内容加上行号后输入 linuxfile2 这个档案里,
cat>filename<<EOF,以EOF作为输入结束,和ctrl+d的作用一样.
6. 服务器会话问题
终端输入 ssh cidi@172.16…,然后输入密码就进入了服务器
screen -S zhz
建立一个zhz的对话,然后可以在这里面训练数据集,即使关掉这个正在训练的终端也不影响训练
screen -ls
是显示有几个screen
screen -r zhz
可以进入zhz的screen看到自己之前在训练的页面
screen -d -r zhz
若zhz是Attached状态,则踢掉远端用户再连接
screen -wipe
检查所有screen,并删除已经无法使用的screen
screen -r 26658.zhz
当你新建了多了zhz,那么就需要加上前面的数字,否则系统不知道你想进入哪个zhz的screen
screen -X -S 26658.zhz quit
删除screen
7. 安装NVIDIA显卡驱动+cuda+cudnn步骤:
- 肖哥拷给我的nvidia文件夹中有一堆文件。
- cd 进nvida文件夹下,
source install_nvidia_driver.sh
- 第一步执行完后会变换到一个黑屏界面,然后按 ctrl + alt + F1 组合键进入命令行界面,输入用户名和密码。【额外介绍一下,ctrl + alt + F7切换回图形化界面】
- cd 进nvidia文件夹下,
source install_cunda.sh
- 第三步安装大概十几分钟结束之后,
sudo service lightdm start
(打开图形化界面),安装结束 - 拷贝环境变量cuda-9.0到 系统中的.bashrc文件最后。直接将以下代码拷贝至.bashrc文件,系统中的.bashrc文件需要ctrl+h才能显示。
# CUDA-9.0
export PATH=/usr/local/cuda-9.0/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64:$LD_LIBRARY_PATH
export C_INCLUDE_PATH=/usr/local/cuda-9.0/include:$C_INCLUDE_PATH
export CPLUS_INCLUDE_PATH=/usr/local/cuda-9.0/include:$CPLUS_INCLUDE_PATH
8. Linux添加打印机
进入 system settings,选择 printers,点击 add ,选择 Network Printer,
选择APPSocket/HP JetDirect,填写 Host, 172.16.34.4,接下来会出现tray3:Not Installed页面才对,
其余的什么也不用填,直接forward,完成。
10.git操作技能
(1)基本命令
git status
git add path/name.txt
git rm --cache path/name.txt # 本地仓库删除文件之后,需要使用git命令删除该文件缓存才能commit。
git commit -m "message"
git pull --rebase
git push origin master
git log
git remote add origin http://172.16.31.6/CIDI-perception/Work-progress.git
git config --global user.email '823655339@qq.com'
(2)怎样把本地文件夹它变成仓库
这样做看似没什么用,但是当你在本地新建好一个仓库的一系列文件的时候,只需要把它添加到远程仓库即可,就不用在远程仓库新建一堆东西了。
看起来这个方法还是没什么用。你把远程仓库clone下来之后,把你写好的东西添加进仓库文件夹之后推送即可。因此,在我本人看来,这种方式创建远程仓库我基本不会用到,但是学习一下总是好的。
首先,本地文件夹名称要与远程仓库名称一致。
git init # 这一步之后,文件夹下会出现.git文件夹
git remote add origin http://... # 添加远程仓库
git pull origin master
git push origin master
git remote add origin http://...
这一步也可以把origin改成别的名称。
注意:最好使用http,因为ssh要设置秘钥之后才能拉取推送文件,目前我还没有弄懂ssh.
(3)怎么修改Git remote add时使用的远程仓库?
git remote add origin http://...
是添加远程仓库
git remote
查看远程仓库
git remote -v
查看远程仓库细节
方法一:
git remote rm origin
git remote add origin git@github.com:Liutos/foobar.git
方法二:把替换成新的url地址。
git remote origin set-url <URL>
方法三:直接修改.git/config文件
(4) git操作时中文文件名乱码
使用git add添加要提交的文件的时候,如果文件名是中文,会显示形如274\232\350\256\256\346\200\273\347\273\223的乱码。
解决方案:在bash提示符下输入:
git config --global core.quotepath false
core.quotepath设为false的话,就不会对0x80以上的字符进行quote。中文显示正常。
16. 如何在README.md文件中添加图片
1、在github上的仓库建立一个存放图片的文件夹,文件夹名字随意。如:img-folder
2、将需要在READNE.md中显示的图片,push到img-folder文件夹中。
3、然后打开github官网,进入仓库的img-folder文件夹中,打开图片,copy网址栏的地址。
4、在README.md中填入:
[外链图片转存失败(img-uVh4faVv-1562320798656)(https://图片地址.png)]
保存即可。
注:![Image text]这个标识不可缺少,不然就把图片显示成网址的文字了。
Image text:指的是如果图片不存在了,要显示的文字说明
19. Linux视频下载神器XDM,堪比windows下IDM
安装教程参考:https://blog.csdn.net/qq378947986/article/details/80821237
安装完成之后,进入任意一个视频网站或者有音频的网站,扩展都可以嗅探到视频和音频的下载地址,通过浏览器右下角出现的DOWNLOAD下载东西。
XDM将自动从浏览器捕获以下类型文件的下载:
3GP,7Z,AVI,BZ2,DEB,DOC,DOCX,EXE,GZ,ISO,MSI,PDF,PPT,PPTX,RAR,RPM,XLS,XLSX,SIT,SITX,TAR,JAR,ZIP,XZ
XDM将在浏览器播放以下类型视频时显示下载选项:
MP4,M3U8,F4M,WEBM,OGG,MP3,AAC,FLV,MKV,DIVX,MOV,MPG,MPEG,OPUS
以上都是默认选项,可以自己添加文件类型。
20.ubuntu强制关闭软件的方法:linux终端kill进程
ubuntu当某个软件不响应卡住了,强制关闭该软件的方法:linux终端kill进程
方法一:
(1)终端输入top
,显示的全是现在系统的进程,按占用资源从多到少排列的找到要关掉的进程,记下该进程第一列的PID编号,然后输入q,退回终端;
(2)输入sudo kill [pid]
即可,也可直接kill [pid],最好使用kill -9 [pid]
强制关闭
方法二:
ps -a 或 ps -A
kill -9 [pid]
或 pkill [进程名称] # 进程名称,不是PID
如果键盘还能响应,就【ctrl + alt + delete】可以弹出【LOG OUT】退出当前账户系统。
另:【alt + F4】可以关闭当前窗口,功能同 【alt+space+c】
22.GPU显存满了, 但是GPU利用率却很低,怎么办?
batch size太小,导致模型的并行化程度太低。还有你的cpu、内存/显存带宽性能不足。
https://blog.csdn.net/cunyizhang/article/details/92771032
https://zhuanlan.zhihu.com/p/53345706
24.使用vim时,vim卡死的解决方法
使用vim时,如果你不小心按了ctrl + s
后,你会发现不能输入任何东西了,像卡死了一般,其实vim并没有卡死,这时vim只是停止向终端输出而已,要想退出这种状态,只需按Ctrl + q
即可恢复正常。
如果要保存的话,使用:wq
即可
29.AP和mAP计算详解(代码全解)
参考:https://mp.weixin.qq.com/s?__biz=MzUxNjcxMjQxNg==&mid=2247490269&idx=3&sn=718b101325a37b152951772e11d4efde&chksm=f9a26852ced5e144200ae2f95d3bd15d9e213dff2728f85defdf75fcd5aeb7acd53f50eb233c&mpshare=1&scene=1&srcid=#rd
Recall和Precision一样,脱离类别是没有意义的。说到Precision(或Recall),一定指的是某个类别的Precision(或Recall)。
目标检测里面没有用准确率Accuracy来评估的,都只用Recall和Precision以及mAP。
(1) Accuracy:准确率
✔️ 准确率=预测正确的样本数/所有样本数,即预测正确的样本比例(包括预测正确的正样本和预测正确的负样本,不过在 【目标检测】 领域,没有预测正确的负样本这一说法,所以目标检测里面没有用Accuracy的)。
Acc = (TP + FN) / num_allSamples
=(TP + TN)/ (TP+TN+FP+FN)
比如说,检测猫,猫以外的其他类别都是负样本,所以负样本不是指一个类别,而是除你要检测的类别以外的所有类别,除非是二分类。【这段话是我添加的】
(2) Precision:查准率
【分母为 所有预测结果为该类别的样本数目】
✔️ recision表示某一类样本预测有多准。
✔️ Precision针对的是某一类样本,如果没有说明类别,那么Precision是毫无意义的(有些地方不说明类别,直接说Precision,是因为二分类问题通常说的Precision都是正样本的Precision)。
Precision = TP/(TP + FP)
比如说,检测猫,分子为标签为猫,预测结果也为猫,即预测正确的样本数;分母为预测结果为猫的所有样本数(注意不是图片数)。
即Precision就是预测猫正确的样本数 占 所有预测结果为猫的样本数。
之所以叫查准率(精确率),是因为预测出了n个该类别的,只预测对了m(m<n)个正确的,所以叫(精确率)查准率。
【上面这两段话是我添加的】
(3) Recall:召回率
【分母为 该类别的所有标签数目】
✔️ Recall和Precision一样,脱离类别是没有意义的。说道Recall,一定指的是某个类别的Recall。Recall表示某一类样本,预测正确的与所有Ground Truth的比例。
Recall = TP/(TP + FN)
✍️ Recall计算的时候,分母是Ground Truth中某一类样本的数量,而Precision计算的时候,是预测出来的某一类样本数。
比如说,检测猫,分子为标签为猫,预测结果也为猫,即预测正确的样本数;分母为把猫检测为猫和把猫检测为非猫的所有样本,即分母是标注的标签中所有为猫的目标总数,不是包含猫的图片的总数,因为每张图片可能有多只猫,每只猫都得算进去。
那么recall就是预测猫正确的样本数 占 所有标签为猫的样本数 的比例。
之所以叫召回率,是因为该类别本来有n个正确的,只召回了m(m<n)个正确的,所以叫召回率。
【上面这两段话是我添加的】
(4) F1 Score:平衡F分数
F1分数,它被定义为查准率和召回率的调和平均数:
F1 = 2* Precision * Recall / (Precision + Recall)
= 2*TP / (2TP + FN + FP)
31.linux下的export命令和环境变量
linux中在 profile 或者 bashrc 或者其他类似的文件中设置环境变量时(比如PATH),如果没有export,那么只能在直接启动的shell中起作用,如果在当前shell下运行脚本或者直接启动一个子shell,因为实际上是局部变量。子shell看不见的,所以就gg了
Linux 指令:系统设置–export
功能说明:设置或显示环境变量。
语 法:export [-fnp][变量名称]=[变量设置值]
补充说明:在shell中执行程序时,shell会提供一组环境变量。export可新增,修改或删除环境变量,供后续执行的程序使用。export的效力仅及于该此登陆操作。
参 数:
-f 代表[变量名称]中为函数名称。
-n 删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中。
-p 列出所有的shell赋予程序的环境变量。
环境变量
https://blog.csdn.net/wl_fln/article/details/7258294
在 linux 里设置环境变量的方法 ( export PATH )
一般来说,配置交叉编译工具链的时候需要指定编译工具的路径,此时就需要设置环境变量。例如我的mips-linux-gcc编译器在“/opt/au1200_rm /build_tools/bin”目录下,build_tools就是我的编译工具,则有如下三种方法来设置环境变量:
1、直接用export命令:
export PATH=$PATH:/opt/au1200_rm/build_tools/bin
查看是否已经设好,可用命令export查看:
[root@localhost bin]:~$ export
declare -x BASH_ENV="/root/.bashrc"
declare -x G_BROKEN_FILENAMES="1"
declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="localhost.localdomain"
declare -x INPUTRC="/etc/inputrc"
declare -x LANG="zh_CN.GB18030"
declare -x LANGUAGE="zh_CN.GB18030:zh_CN.GB2312:zh_CN"
declare -x LESSOPEN="|/usr/bin/lesspipe.sh %s"
declare -x LOGNAME="root"
declare -x LS_COLORS="no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=01;32:*.cmd=01;32:*.exe=01;32:*.com=01;32:*.btm=01;32:*.bat=01;32:*.sh=01;32:*.csh=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tz=01;31:*.rpm=01;31:*.cpio=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.xbm=01;35:*.xpm=01;35:*.png=01;35:*.tif=01;35:"
declare -x MAIL="/var/spool/mail/root"
declare -x OLDPWD="/opt/au1200_rm/build_tools"
declare -x PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin:/opt/au1200_rm/build_tools/bin"
declare -x PWD="/opt/au1200_rm/build_tools/bin"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_ASKPASS="/usr/libexec/openssh/gnome-ssh-askpass"
declare -x SSH_AUTH_SOCK="/tmp/ssh-XX3LKWhz/agent.4242"
declare -x SSH_CLIENT="10.3.37.152 2236 22"
declare -x SSH_CONNECTION="10.3.37.152 2236 10.3.37.186 22"
declare -x SSH_TTY="/dev/pts/2"
declare -x TERM="linux"
declare -x USER="root"
declare -x USERNAME="root"
可以看到灰色部分有设置的路径,说明环境变量已经设好,PATH里面已经有了我要加的编译器的路径。
2、修改profile文件:
vi /etc/profile
在里面加入:
export PATH="$PATH:/opt/au1200_rm/build_tools/bin"
3. 修改.bashrc文件:
vi /root/.bashrc
在里面加入:
export PATH="$PATH:/opt/au1200_rm/build_tools/bin"
后两种方法一般需要重新注销系统才能生效,最后可以通过echo命令测试一下:
echo $PATH
看看输出里面是不是已经有了 /my_new_path这个路径了。
另有:4. 修改/etc/re.local文件:
# vi /etc/re.local
在里面加入:
export PATH="$PATH:/opt/au1200_rm/build_tools/bin"
**===================================================================**
“/bin”、“/sbin”、“ /usr/bin”、“/usr/sbin”、“/usr/local/bin”等路径已经在系统环境变量中了,如果可执行文件在这几个标准位置,在终端命令行输入该软件可执行文件的文件名和参数(如果需要参数),回车即可。
如果不在标准位置,文件名前面需要加上完整的路径。不过每次都这样跑就太麻烦了,一个“一劳永逸”的办法是把这个路径加入环境变量。命令 export P A T H = " 路 径 ” ( 或 “ P A T H = PATH="路径”(或“PATH= PATH="路径”(或“PATH=PATH:路径”) ( P A T H 为 环 境 变 量 名 , 如 D V S D K ; 调 用 时 用 PATH为环境变量名,如DVSDK;调用时用 PATH为环境变量名,如DVSDK;调用时用DVSDK)可以把这个路径加入环境变量,但是退出这个命令行就失效了。
要想永久生效,需要把这行添加到环境变量文件里。有两个文件可选:“/etc/profile”和用户主目录下的“.bash_profile”,“/etc/profile”对系统里所有用户都有效,用户主目录下的“.bash_profile”只对这个用户有效。
export P A T H = " PATH=" PATH="PATH:路径1:路径2:…:路径n” (或“PATH= P A T H : 路 径 1 : 路 径 2 : . . . : 路 径 n " ) , 意 思 是 可 执 行 文 件 的 路 径 包 括 原 先 设 定 的 路 径 , 也 包 括 从 “ 路 径 1 ” 到 “ 路 径 n ” 的 所 有 路 径 。 当 用 户 输 入 一 个 一 串 字 符 并 按 回 车 后 , s h e l l 会 依 次 在 这 些 路 径 里 找 对 应 的 可 执 行 文 件 并 交 给 系 统 核 心 执 行 。 那 个 “ PATH:路径1:路径2:...:路径n" ),意思是可执行文件的路径包括原先设定的路径,也包括从“路径1”到“路径n”的所有路径。当用户输入一个一串字符并按回车后,shell会依次在这些路径里找对应的可执行文件并交给系统核心执行。那个“ PATH:路径1:路径2:...:路径n" ),意思是可执行文件的路径包括原先设定的路径,也包括从“路径1”到“路径n”的所有路径。当用户输入一个一串字符并按回车后,shell会依次在这些路径里找对应的可执行文件并交给系统核心执行。那个“PATH”表示原先设定的路径仍然有效,注意不要漏掉。某些软件可能还有“PATH”以外类型的环境变量需要添加,但方法与此相同,并且也需要注意“$”。
注意,与DOS/Window不同,UNIX类系统环境变量中路径名用冒号分隔,不是分号。另外,软件越装越多,环境变量越添越多,为了避免造成混乱,建议所有语句都添加在文件结尾,按软件的安装顺序添加。
格式如下():
# 软件名-版本号
PATH=$PATH:路径1:路径 2:…:路径n
其他环境变量=$其他环境变量:…
在“profile”和“.bash_profile”中,“#”是注释符号,写在这里除了视觉分隔外没有任何效果。
设置完毕,注销并重新登录,设置就生效了。如果不注销,直接在shell里执行这些语句,也能生效,但是作用范围只限于执行了这些语句的shell。
相关的环境变量生效后,就不必老跑到软件的可执行文件目录里去操作了。
32.升级cudnn与更新显卡驱动
(1)升级cudnn,参考一下博客
https://blog.csdn.net/zong596568821xp/article/details/86098833
需要注意的是,我的电脑查看cudnn版本命令为cat /usr/include/cudnn.h | grep CUDNN_MAJOR -A 2
,
并不是cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2
,因为安装时候的路径不同,所以需要注意。
我的电脑查看cuda版本命令为cat /usr/local/cuda/version.txt
,这个路径是一致的。后面的
sudo rm -rf /usr/local/cuda/include/cudnn.h
sudo rm -rf /usr/local/cuda/lib64/libcudnn*
sudo cp include/cudnn.h /usr/local/cuda/include/
三条命令也需要修改路径为
sudo rm -rf /usr/include/cudnn.h
sudo rm -rf /usr/local/cuda/lib64/libcudnn*
sudo cp include/cudnn.h /usr/include/
(2)更新显卡驱动
参考 https://blog.csdn.net/breeze5428/article/details/80013753
linux安装有道词典不能启动
参考:https://ywmy210.github.io/ywmy/2018/11/25/ubuntu-18-04%E6%9C%89%E9%81%93%E8%AF%8D%E5%85%B8%E5%AE%89%E8%A3%85/
linux安装有道词典后,不能启动有道词典的解决方法:
安装有道词典
下载编译过的安装包
wget https://github.com/yomun/youdaodict_5.5/raw/master/youdao-dict_1.1.1-0~ubuntu_amd64.deb
编译的安装包需要3D加速
按以下命令查询并卸载QT5,如有显示 PyQt5 (5.10.1), 卸载之…
pip3 list | grep PyQt5
pip3 uninstall pyqt5
root 用户也一样要
sudo sudo pip3 list | grep PyQt5
sudo sudo pip3 uninstall pyqt5
安装依赖包
sudo apt install python3
sudo apt install python3-dbus python3-lxml python3-pil python3-requests python3-xdg python3-xlib
sudo apt install python3-pyqt5 python3-pyqt5.qtmultimedia python3-pyqt5.qtquick python3-pyqt5.qtwebkit
sudo apt install gir1.2-appindicator3-0.1 qml-module-qtgraphicaleffects qml-module-qtquick-controls
sudo apt install libqt5multimedia5-plugins ttf-wqy-microhei
sudo apt install tesseract-ocr tesseract-ocr-eng tesseract-ocr-chi-sim tesseract-ocr-chi-tra
sudo apt install ubuntu-restricted-extras
Ubuntu 18.04 用 fonts-wqy-microhei 取代了 ttf-wqy-microhei
安装有道词典
sudo dpkg -i youdao-dict_1.1.1-0?ubuntu_amd64.deb
39.打印CSDN网页内容,并去掉网页两边的广告
打印CSDN内容,按F12
进入开发者模式,将以下js代码复制放入Chrome开发者选项里边的console
,回车,会弹出一个保存为pdf的会话框,save
后即可看到pdf中已经只剩下网页中需要保存的内容,两边没有广告。
(function(){
$("#side").remove();
$("#comment_title, #comment_list, #comment_bar, #comment_form, .announce, #ad_cen, #ad_bot").remove();
$(".nav_top_2011, #header, #navigator").remove();
$(".p4course_target, .comment-box, .recommend-box, #csdn-toolbar, #tool-box").remove();
$("aside").remove();
$(".tool-box").remove();
$("main").css('display','content');
$("main").css('float','left');
window.print();
$("tool-box").remove();
})();
40.安装tensorrt和遇到的问题及解决方法方法
安装TensorRT-5.0.2.6版本的安装包TensorRT-5.0.2.6.Ubuntu-16.04.4.x86_64-gnu.cuda-9.0.cudnn7.3.tar.gz,对应cuda-9.0.cudnn7.3。
安装参考:https://blog.csdn.net/xulei_Tao/article/details/90339694
出现问题参考:https://www.twblogs.net/a/5d0f8bfabd9eee1ede048927/zh-cn
gedit ~/.bashrc
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/zhz/Downloads/TensorRT-5.0.2.6/lib
export CUDA_INSTALL_DIR=/usr/local/cuda-9.0 ##这个和下面这个最好加上,不然可能会出错
export CUDNN_INSTALL_DIR=/usr/local/cuda-9.0
source ~/.bashrc
100.linux内核切换
参考:
只看这个,这个解决了我的问题:http://xiexiejiao.cn/linux/change-linux-image-on-ubuntu1604.html
https://blog.csdn.net/DL_ChenBo/article/details/52400044
https://blog.csdn.net/u011304615/article/details/70920171
当不能连接无线网时,也可以切换到原来的内核来解决,我联网问题虽然解决的,但是内核版本却更新到了最新,而不是回退,我不知道怎么回事。
sudo gedit /etc/default/grub
将GRUB_DEFAULT=0修改为你所想要还原的版本号, 如:GRUB_DEFAULT=“Ubuntu, with Linux 3.2.0-23-generic”
当我们把版本回退后删除了一大堆内核,出现了系统不正常,无法连接网络和wifi.这个时候就需要下载三个linux内核的.deb文件后分别安装(例如:linux-image-4.15.10-041510-generic_4.15.10-041510.201803152130_amd64.deb、linux-headers-4.15.10-041510_4.15.10-041510.201803152130_all.deb、linux-headers-4.15.10-041510-generic_4.15.10-041510.201803152130_amd64.deb这三个),sudo dpkg -i *.deb
;
然后 sudo gedit /etc/default/grub
修改将GRUB_DEFAULT=0修
改为你所想要还原的版本号, 如:GRUB_DEFAULT=“Ubuntu, with Linux 3.2.0-23-generic”,然后sudo update-grub
;
最后锁定当前内核版本使之在apt dist-upgrade时也不会被升级:```apt-mark hold linux-image-4.4.0-97-generic````
101. ssh登录与scp文件拷贝
使用ssh登录远程的话,端口是小写的 -p,ssh -p 22 mdc@172.16.34.17
使用scp拷贝文件的话是端口大写的 -P
使用ssh的scp传送文件(夹),都是在本机终端路径下进行传送文件命令,并且 -P 是大写的P,-r 是传送文件夹:
从远程终端传送文件到本机:scp -P 远程端口号 mdc@172.16.34.17:远程文件路径 本地路径
从远程终端传送文件夹到本机:scp -P 远程端口号 -r mdc@172.16.34.17:远程文件夹路径 本地路径
或者:scp -rP 远程端口号 mdc@172.16.34.17:远程文件夹路径 本地路径
从本机终端传送文件到远程:scp -P 远程端口号 本地文件 mdc@172.16.34.17:远程路径
从本机终端传送文件夹到远程:scp -P 远程端口号 -r 本地文件 mdc@172.16.34.17:远程路径
或者:scp -rP 远程端口号 本地文件 mdc@172.16.34.17:远程路径
102.忘记root密码
参考 https://www.linuxidc.com/Linux/2016-05/131256.htm
(1) 忘了root密码却想进入root用户,如果用户具有sudo权限,那么直接可以运行如下命令:
sudo su root
passwd:输入用户密码
然后就进入了root下。
(2)更改root密码
直接运行sudo passwd root
命令就可以直接更改root密码。
(3)有关sudo su的区别:
1.共同点:都是root用户的权限;
2.不同点:su仅仅取得root权限,工作环境不变,还是在切换之前用户的工作环境;sudo是完全取得root的权限和root的工作环境。
103.mdc挂载NAS
能不能挂载上,首先要进行ping ip地址
操作,ping得通才能挂载上。
1.安装NFS服务:
参考 https://blog.csdn.net/CSDN_duomaomao/article/details/77822883
执行以下命令安装NFS服务器,
# apt会自动安装nfs-common、rpcbind等13个软件包
sudo apt install nfs-kernel-server
启动nfs:
service nfs-server start
但是【在mdc上安装失败】的解决方法:
(1) 先确认mdc能够访问外网:ping baidu.com
(2) 修改apt源地址,把源修改为中科大镜像:
su #进入root
vim /etc/apt/source.list
#把该文件内容替换为下面内容:
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial main multiverse restricted universe
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-backports main multiverse restricted universe
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-security main multiverse restricted universe
deb http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-updates main multiverse restricted universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial main multiverse restricted universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-backports main multiverse restricted universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-security main multiverse restricted universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-ports/ xenial-updates main multiverse restricted universe
deb http://mirrors.ustc.edu.cn/ros/ubuntu/ xenial main
(3)再更新apt源,这一步至关重要:
apt-get update
(4)安装nfs
apt install nfs-kernel-server
2.挂载与卸载:
能不能挂载上,首先进行ping ip地址
操作,ping得通才能挂载上,不同网段是ping不通的。
使用su
进入root下或者sudo
运行以下命令:
sudo mount -t nfs 172.16.34.190:/volume1/data /mnt/nas
如果想取消挂载,可以使用umount
命令:
## 方法1:
umount /mnt/nas
## 方法2:
umount 172.16.34.190:/volume1/data
## 方法3:
umount 172.16.34.190:/volume1/data /mnt/nas
如果提示umount: /mnt/usb: target is busy
,可尝试强制卸载:
## 强制卸载:
umount -f /mnt/nas
如果尝试 umount -f /mnt/nas
还是失败,可以使用下面命令:
fuser -ck /mnt/nas
或者fuser -mk /mnt/nas
可以杀死相关进程,然后再执行umount /mnt/nas
即可卸载成功.
以下是相关资料:
fuser -cu /mnt/usb #查看挂载文件进程
fuser -mv /dev/sdb #或者查看挂载点进程
fuser -ck /mnt/usb #结束进程
fuser -mk /dev/sdb #使用挂载点结束进程
3.设置重启后自动挂载
(参考:原文链接:https://blog.csdn.net/qq_40338425/article/details/95169567)
有时会发现,挂载成功的NAS在服务器重启后会消失,所以我们要设置自动挂载NAS,方法如下:
sudo vim /etc/rc.local
加入第二步执行的挂载命令:
mount -t nfs 172.16.34.190:/volume1/data /mnt/nas
这样重启后会自动挂载。
可能会出现的问题(我用笔记本没出现下面的问题):
如果重启后发现未挂载,那可能是您的启动文件没有执行权限(可执行权限是rwx中的x)。值得注意的是,不要纠结/etc/rc.local这个文
件的权限,因为真实执行的是/etc/rc.d/rc.local文件(我笔记本没这个文件),执行命令加执行权限chmod 755 /etc/rc.d/rc.local
【可能出现的问题】:
【1】如果挂载命令一直无响应卡在那,可能是NAS中没有启用NFS,可以在NAS的网页界面的控制面板中找到"File Services",里面的"SMB/AFP/NFS"的最下面打勾启用NFS。
【2】挂载时候,如果出现这种错误mount.nfs: access denied by server while mounting 172.16.88.80:/volume1/data
挂载失败,可使用如下方法解决:
原因是nas没有设置nfs服务器,不设置的话,别的主机想挂载它,就没有权限。可以在nfs服务器文件中添加主机。
参考博客:https://blog.csdn.net/kevinhg/article/details/5967432 NFS服务器设置及mount命令挂载
(1)登录进nas的终端(注意:不是登录进你想挂载到的主机的终端):
sudo vim /etc/exports # 如果没有exports文件可以自己创建
(2)然后把下面这句话加入进取,注意修改ip地址,这个ip地址是你想要把nas挂载到的服务器的IP地址,不是nas的ip:
/volume1/data 192.168.1.6/24(rw,async,no_wdelay,crossmnt,insecure,all_squash,insecure_locks,sec=sys,anonuid=1024,anongid=100)
/volume1/data
是nas上的共享目录,接下来除了ip地址需要修改,后面的括号中默认不用修改,如有疑问可以查阅前面的参考博客。
(3)使改动立刻生效,重新mount 上一步/etc/exports
中的共享目录:
exportfs -rv
(4)切换窗口登录到主机终端,并使用挂载命令进行挂载:
mount -t nfs 172.16.34.190:/volume1/data /mnt/nas
(5)上一步挂载成功后,继续在主机设置开机自动挂载nas:
sudo vim /etc/rc.local
往里面加入挂载命令:
mount -t nfs 172.16.34.190:/volume1/data /mnt/nas
这样即使主机重启后也会自动挂载。
【注意】:(1) 这里可能存在路径不对而出现类似"mount.nfs: Failed to resolve server 172.16.34.190/: Temporary failure in name resolution"
的问题。可以使用ssh登录NAS,在data路径下使用pwd
查看路径。
(2) 设置ssh登录NAS,需要在群晖NAS页面下的控制面板的"终端机和SNMP"选项勾选"启用ssh功能"。
(3) 上面的172.16.34.190是NAS的ip地址,/volume1/data是NAS的共享文件夹。
4.在NAS上插上移动硬盘或优盘拷贝数据的方法:
(1)方法1:(图形化界面,拷贝也很快,推荐)
在笔记本电脑上打开谷歌浏览器,输入http://find.synology.com/
然后输入账号cidi
和密码qwertyuiop
,打开File Station
就会看到两个文件夹data
和usbshare1
,data
是mdc上挂载的nas共享文件夹,
usbshare1
自己的U盘,,再打开一个File Station
,自己在两个File Station
之间拖拽文件进行复制。
拷贝完之后,在usbshare1
上右键选择退出
,弹出U盘。
(2)方法2:(命令行操作,路径有点乱,自己先在实验室mdc上操作熟悉一下)
ssh登录上NAS,df -h
可以看到刚刚插入的硬盘/volumeUSB1/usbshare
,还有一个/volume1
是nas硬盘,以拷贝nas硬盘上的perception_node文件到usb移动硬盘上为例:
cp /volume1/data/mdc/ip17/nas/zhz/release/bin/perception_node /volumeUSB1/usbshare/
。
不知道路径可以依次敲两下Tab
键来看目录下有哪些目录。
即:NAS的硬盘是volume1,在volume1下新建了一个共享文件夹data
,然后把这个/volume1/data/
文件夹挂载到mdc上的/mnt/nas/
,在mdc的/mnt/nas/
目录下新建mdc/ip17/nas/
后得到路径/mnt/nas/mdc/ip17/nas/
,
再把/mnt/nas/mdc/ip17/nas/
做一个软链接nas放到mdc的home目录/home/mdc/
下,即/home/mdc/nas
(这就是我们平时访问的那个目录,该目录其实是个软链接)。所以拷贝的话,路径比较复杂。
- tips:
网线插在交换机上没网络,但是同一个交换机上的ip是一个网段的,它们之间可以ping通,可以ssh登录。
给电脑绑定静态ip的方法:网络,编辑连接,选中有线连接,编辑,ipv4设置,手动(manual),add,输入自己想绑定的ip地址,(子网掩码随便设置为16或24或255.255.0.0或255.255.255.0都行如果想连上英特网,还得设置网关,ip的最后一个改成1就是网关,dns服务器设置为8.8.8.8,)然后点击保存即可。想要变回随机分配IP,就重复前面的步骤,把手动改为自动(DHCP)即可。
NAS有两个网卡,其中一个绑定静态ip,另一个随机分配IP。可以ssh登录静态IP地址,然后ifconfig会看到两个网卡和ip,记下另一个随机IP地址(不换网口,这个ip一般就不会变化),然后就可以使用 ftp://IP 来登录ftp了(因为之前NAS设置过打开ftp和ssh开关,下次更换了IP地址后就不用再重新设置打开ftp和ssh了)。
群晖NAS:
群晖NAS账号:cidi
密码:qwertyuiop
(1)把群晖NAS插电联网之后,输入这个网址扫描群晖NAS:http://find.synology.com/
,注意NAS联网的ip和必须和电脑的ip在同一个局域网,否则会搜索不到NAS。有时候很邪乎,换好几个网口都搜不到NAS,所以最好是把PC和NAS连接在一台交换机,可以保证他们在同一网段,一定可以搜到NAS.
(2)搜索到NAS之后就输入NAS的账号和密码登陆进去,然后在"控制面板"或者"File station"新建共享文件夹。然后再进行挂载操作。
(3)如果你需要挂载在别的服务器(比如mdc上,但是mdc上不能登录网页查看到NAS的ip,所以前提是你先知道NAS的ip是多少)上,要挂载到的那个服务器的ip也必须和NAS在同一个局域网。
104.创建软链接
ln -s 源路径 目标路径(名称)
例如 ln -s /home/zhz/work /home/zhz/Desktop/link_to_work
就会在Desktop目录下生成一个link_to_work的软链接(快捷方式)
105.将ubuntu电脑设置为一台可远程ssh访问的服务器
参考 原文链接:https://blog.csdn.net/papaaa/article/details/77366382
其实,将ubuntu系统设置为服务器很简单,只需要开启ssh服务就可以了。开启了ssh服务以后,其它电脑就可以通过ssh登录你的这台ubuntu服务器。SSH分客户端openssh-client和openssh-server,但是ubuntu系统已经默认有openssh-client(再说作为服务器也不需要这个),所以你现在只需要安装openssh-server就可以达到目的。
安装openssh-server:
1、在 ubuntu Terminal 下输入命令:sudo apt-get update
2、在 ubuntu Terminal 下输入命令:sudo apt-get install openssh-server
如果没有报错openssh-server
已经安装好了,接下来你需要查看ssh服务是否开启,在Terminal输入命令 ps -e |grep ssh
,如果出现sshd则已经开启,如下7124 ? 00:00:00 sshd
;
否则就是没有开启,需要输入命令sudo /etc/init.d/ssh start
开启服务,为了确定开启服务,再用上述命令查看。
在开启ssh服务以后,你就可以在其它电脑来访问你的ubuntu系统了,噢,对了,开启的默认端口是22。如果在ubuntu登录,直接用ssh username@192.168.1.1
username为192.168.1.1机器上的用户名,需要输入密码,密码为ubuntu机器上的用户密码(执行sudo命令需要输入的那个)。如果在windows系统登录,需要下载支持ssh的软件,博主一直在使用putty(端口号为22)。
106.在ubuntu电脑(或服务器)登录另一台ubuntu电脑(或服务器)的文件系统sftp/ftp
(1)ftp
sudo apt-get install vsftpd # 安装ftp服务
service nvsftpd start #启动ftp服务
service nvsftpd status #查看ftp服务状态
然后就可以使用ftp方式连接本服务器了
(2)sftp
方法: sftp://172.16.34.96/home/zhz
例如,我随意打开自己ubuntu电脑的一个文件夹,在最左侧目录一栏的最下方会有一个"Connect to Server"【连接到服务器】,点击它,输入格式如下:sftp://172.16.34.96/home/zhz
,
172.16.34.96
是你想登录的另一台ubuntu电脑的ip,zhz
是那台电脑的用户名,,然后输入密码就可以登录到另一台电脑的文件系统, 然后就可以操作服务器那边的文件像操作自己电脑上的文件一样,随意复制或新建或下载到本机上。
该方法可以操作文件,ssh
方法可以使用命令行的方式进行操作文件或者运行其他命令,但是他们都不能够在本机上显示你想得到的程序的图形化界面。
107.端口映射ping不同的解决办法
192.168.1.6端口映射为172.18.2.244,但是ping不通172.16.xx.xx网段的NAS网络存储器,所以挂载不了NAS,解决办法就是
sudo vim /etc/network/interfaces
auto lo
iface lo inet loopback
auto enp125s0f0 # 这是一个网卡
iface enp125s0f0 inet static
address 192.168.1.6 #注意这个ip是外网ip,通过这个ip来映射为内网172.18.2.244
netmask 255.255.255.0
gateway 192.168.1.1 ### 这句话是需要添加的
auto enp125s0f2 # 这是另一个网卡
iface enp125s0f2 inet static
address 192.168.3.6
netmask 255.255.255.0
在上面的对应网卡添加网关 gateway 192.168.1.1
后,重启,就可以ping通了
108.nas服务器或Red-Hat系统设置静态ip
当我们只能命令行访问服务器时候,就不能使用图形化界面来设置静态ip了,就得使用命令行配置静态ip。
输入ifconfig查看网卡和ip信息
如果输入“ifconfig”命令时提示找不到命令,
apt install net-tools
sudo vim /etc/sysconfig/network-scripts/ifcfg-enp3s0 # 这里/ifcfg-enp3s0每个人的名称后缀都不一样,前缀都是/ifcfg-enp,要找你自己实际的
在阅读模式下,输入“i”进入到编辑模式
BOOTTROPO:代表的是获取ip方式(“dhcp”=动态获取/“static”=设置静态ip)
IPADDR:代表ip地址,这里可以自己指定的地址
NETMASK:代表子网掩码,使用刚才查看的子网掩码
GATEWAY:代表网关,因为我的是192.168.2网段,所以网关就用192.168.2.1就可以
最后就是保存生效后,重启系统就可以。
108.1.Ubuntu系统设置静态ip
首先打开终端,输入命令 sudo vim /etc/network/interfaces 进入到文件中开始我们的配置
只需要在该文件中添加如下内容:
auto ens33 #网卡名
iface ens33 inet static #设置为静态
address 192.168.190.3 #IP地址
netmask 255.255.255.0 #子网掩码
gateway 192.168.190.2 #网关
dns-nameserver 114.114.114.114 #DNS服务器
109.mdc设置访问外网
mdc访问外网:
首先第一步,在实验室的主机电脑上打开虚拟机,开启cenos8,打开它才能让mdc上网。(车上访问外网不需要这一步)
然后在mdc终端root用户下,新建了一个脚本route.sh,脚本内容如下:
ip route add default via 192.168.1.1 dev enp125s0f0
route add default gw 192.168.1.1 #添加网关,如果windows电脑上的有一个ip是192.168.1.2,那么网关也要改为192.168.1.2
echo nameserver 114.114.114.114 | tee /etc/resolv.conf # 把 "nameserver 114.114.114.114"这句话输入到/etc/resolv.conf文件中,nameserver 114.114.114.114是DNS
# echo 'nameserver 114.114.114.114' >> /etc/resolv.conf #这句话和上面一句命令等价
然后运行 bash route.sh
应该就能访问外网了。
/etc/resolv.conf
是DNS客户机配置文件,用于设置DNS服务器的IP地址及DNS域名,还包含了主机的域名搜索顺序。
关于/etc/resolv.conf
可参考 https://www.cnblogs.com/mafeng/p/10500548.html
110.DNS、网关、子网掩码、端口映射、路由器、交换机
【1.DNS】
DNS(Domain Name System/Server)是域名服务器,它将人类可读的名称(如www.example.com) 转换为数字IP 地址(如192.0.2.1),供计算机用于相互连接。
114.114.114.114是国内移动、电信和联通通用的DNS,解析成功率相对来说更高度,国内用户使用的比较多,速度相对快、稳定,是国内用户上网常用的DNS。
8.8.8.8是GOOGLE公司提供的DNS,该地址是全球通用的,相对来说,更适合国外以及访问国外网站的用户使用。
【2.网关】
网关是一种充当转换重任的计算机系统或设备。使用在不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。从一个房间走到另一个房间,必然要经过一扇门。同样,从一个网络向另一个网络发送信息,也必须经过一道“关口”,这道关口就是网关。顾名思义,网关(Gateway) 就是一个网络连接到另一个网络的“关口”。也就是网络关卡。
网关实质上是一个网络通向其他网络的IP地址。比如有网络A和网络B,网络A的IP地址范围为“192.168.1.1~192. 168.1.254”,子网掩码为255.255.255.0;网络B的IP地址范围为“192.168.2.1~192.168.2.254”,子网掩码为255.255.255.0。在没有路由器的情况下,两个网络之间是不能进行TCP/IP通信的,即使是两个网络连接在同一台交换机(或集线器)上,TCP/IP协议也会根据子网掩码(255.255.255.0)判定两个网络中的主机处在不同的网络里。而要实现这两个网络之间的通信,则必须通过网关。如果网络A中的主机发现数据包的目的主机不在本地网络中,就把数据包转发给它自己的网关,再由网关转发给网络B的网关,网络B的网关再转发给网络B的某个主机。
【3.子网掩码】
子网掩码是一个32位的2进制数, 其对应网络地址的所有位都置为1,对应于主机地址的所有位都置为0。子网掩码告知路由器,地址的哪一部分是网络地址,哪一部分是主机地址,使路由器正确判断任意IP地址是否是本网段的,从而正确地进行路由。网络上,数据从一个地方传到另外一个地方,是依靠IP寻址。从逻辑上来讲,是两步的。第一步,从IP中找到所属的网络,好比是去找这个人是哪个小区的;第二步,再从IP 中找到主机在这个网络中的位置,好比是在小区里面找到这个人。
子网掩码不能单独存在,它必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分。
【4.路由器】
路由器是连接两个或多个网络的硬件设备,在网络间起【网关】的作用,是读取每一个数据包中的地址然后决定如何传送的专用智能性的网络设备。它能够理解不同的协议,例如某个局域网使用的以太网协议,因特网使用的TCP/IP协议。这样,路由器可以分析各种不同类型网络传来的数据包的目的地址,把非TCP/IP网络的地址转换成TCP/IP地址,或者反之;再根据选定的路由算法把各数据包按最佳路线传送到指定位置。所以路由器可以把非TCP/ IP网络连接到因特网上。
【5.交换机】
交换机(Switch)意为“开关”是一种用于电(光)信号转发的网络设备。它可以为接入交换机的任意两个网络节点提供独享的电信号通路。最常见的交换机是以太网交换机。
交换是按照通信两端传输信息的需要,用人工或设备自动完成的方法,把要传输的信息送到符合要求的相应路由上的技术的统称。交换机根据工作位置的不同,可以分为广域网交换机和局域网交换机。广域的交换机就是一种在通信系统中完成信息交换功能的设备,它应用在数据链路层。交换机有多个端口,每个端口都具有桥接功能,可以连接一个局域网或一台高性能服务器或工作站。实际上,交换机有时被称为多端口网桥。
【6.端口映射】
目前不少企业都已建好了内部局域网,但随着互联网时代的到来,仅搭建局域网已经不能满足众多企业的需要,有更多的用户需要在 Internet上发布信息,或进行信息检索,将企业内联网接入 Internet已经成为众多企业的迫切要求。但是,随着因特网的迅速发展,IP地址短缺已成为一个十分突出的问题,企业中不可能每台电脑都拥有一个真实的IP地址,所以大部分的企业用户都是通过网关或代理服务器上网,而内部的电脑只有一个网内的IP地址这样做的好处虽然节约了IP地址资源,但是有很多地方不方便,因为企业的网络很多是要对外的,由于网内的电脑采用网关和代理上网,本身没有对外可访问的IP地址,所以造成外界无法访问这些电脑。又不能把企业的所有服务器全部放在作为代理服务器的一台电脑上,这时候就要用到端口映射了。
即:IP短缺,利用端口映射把一个真实IP映射出很多“虚假”ip,我们都是用的这些虚假ip。
【7.以太网】
以太网是一种计算机局域网技术。它是目前应用最普遍的局域网技术。以太网是现实世界中最普遍的一种计算机网络。以太网有两类:第一类是经典以太网,第二类是交换式以太网,使用了一种称为【交换机】的设备连接不同的计算机。经典以太网是以太网的原始形式,运行速度从3~10 Mbps不等;而交换式以太网正是广泛应用的以太网,可运行在100、1000和10000Mbps那样的高速率,分别以快速以太网、千兆以太网和万兆以太网的形式呈现。
111.ssh登录输入密码次数过多被锁住的解决办法
当ssh登录用户输入用户密码次数过多被锁住出现这种情况:
Account locked due to 25 failed logins
解决办法:
在服务器上,root终端下:
pam_tally2 --user=user_name #查看,user_name是被锁住的远程用户名
pam_tally2 --user=user_name --reset #重置
112.ssh登录服务器一直被拒绝的解决办法
ssh登录服务器,密码正确但是一直出现下面这种情况:
Permission denied, please try again.
解决方法:
因为服务器默认该用户没有权限登录上去,所以需要在服务器上设置:
在服务器root终端下:
# 在root权限下
cd /home/mdc/bin/
./enable_sudo_for_ordinary_user.sh -u user_name # 把user_name改为你登录不上的远程用户名
113.Ubuntu下的ssh连接总是自己断开的解决办法
Ubuntu的ssh保持长时间连接
有时候在Ubuntu下的ssh连接老是自己会断,一段时间不理它就会失去响应.如何让ssh连接服务器或者sshtunnel保持连接呢?
解决办法:
针对mdc上可以这么设置:
root下,vim /etc/ssh/sshd_config
,将ClientAliveInterval
和ClientAliveCountMax
的值都设为300
方法1:
在服务器上 /etc/profile
文件下最后有个
export TMOUT=300
,单位是秒,修改这个值为3600可以让它在一小时不掉线。
source /etc/profile
执行该命令令其立即生效。
方法2:(不靠谱)
转自:http://www.fu-he.com/linux/jishu_d.asp?id=3939
有时候在Ubuntu下的ssh连接老是自己会断,一段时间不理它就会失去响应.如何让ssh连接服务器或者sshtunnel保持连接呢?
解决办法:
只要在/etc/ssh/ssh_config
文件里加两个参数就行了
TCPKeepAlive yes
ServerAliveInterval 300
前一个参数是说要保持连接,后一个参数表示每过5分钟发一个数据包到服务器表示"我还活着"。
如果你没有root权限,修改或者创建~/.ssh/ssh_config也是可以的.【这个没试验】
114.当前运行的docker修改环境后,想在本地保存下来的方法
docker images 查看所有镜像
docker ps # 查看当前运行的镜像
docker commit -m="123" NAMES name # NAMES是通过docker ps 查看到的NAMES,name是自己取的别名
# 例如:docker commit -m="123456" squirrel_docker docker_zhz
docker pull 172.16.31.100:5000/squirrel:dev-latest # 拉取镜像
docker run ..... # 运行镜像
docker stop $(docker ps -a -q) # 停止所有docker容器,docker外执行
115.shell语法
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
$! 后台运行的最后一个进程的ID号
$$ 脚本运行的当前进程ID号
$0 执行的文件名
$1 传入的第一个参数
& shell命令以&结尾,就可以后台运行,如:roscore&
shift 命令每执行一次,变量的个数($#)减一,而变量值提前一位.
也可以shift后加数字参数,如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1、$2、$3丢弃,$0不移动。不带参数的shift命令相当于shift 1。
示例如下:
#测试 shift 命令(x_shift.sh)
until [ $# -eq 0 ]
do
echo "第一个参数为: $1 参数个数为: $#"
shift
done
执行以上程序x_shift.sh:
$./x_shift.sh 1 2 3 4
结果显示如下:
第一个参数为: 1 参数个数为: 4
第一个参数为: 2 参数个数为: 3
第一个参数为: 3 参数个数为: 2
第一个参数为: 4 参数个数为: 1
------------------------------------------------------------------
[ -e $var ] 文件是否存在
[ -d $var ] 是否是目录
[ -f $var ] 是否是文件
[[ $var1 = $var2 ]] 两个字符串是否相同
[ $var -eq 0 ] 一个变量是否为0
[ $a -gt $b ] a 大于 b
[ $a -lt $b ] a 小于 b
-----------------------------------------------------------------
set
set -e 执行的时候如果出现了返回值为非零,整个脚本 就会立即退出。 你写的每个脚本都应该在文件开头加上set -e,这句语句告诉bash如果任何语句的执行结果不是true则应该退出.
set +e 执行的时候如果出现了返回值为非零将会继续执行下面的脚本
#!/bin/sh -e
或#!/bin/bash -e
放在脚本第一行,和set -e
功能也一样
set -x 用于脚本调试,在liunx脚本中可用set -x就可有详细的日志输出.免的老是要echo了
read用法:
read既可以从键盘读取,也可以读取文件的一行.
read a # 这个命令执行后,会要求从键盘输入内容
1234 # 这是键盘输入1234
echo $a # 会输出 1234
下面是read读取文本文件的一行内容:
while 循环读取文本文件$release_conf的内容:
其中文本文件中全部存放的是变量赋值,如某一行:work_path=/home/zhu/
while read line;do
eval "$line"
done < $release_conf
然后,文件中的每一行变量就可以被后续的代码使用了,因为执行了一句 eval "$line" ,他就把 work_path=/home/zhu/ 给执行了
--------------------------------------------------------------------------------------------------------------
pgrep, pkill
pgrep -f abc 匹配出含abc的进程 并输出进程的pid
pkill -f abc 结束含abc的所有进程
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 详解参考https://blog.csdn.net/davidhopper/article/details/78989369
pkill -SIGINT -f record 结束进程名包含record的进程,SIGINT与字符ctrl+c关联,只能结束前台进程
--------------------------------------------------------------------------------------------------------------
dirname, basename
dirname命令去除文件名中的非目录部分,删除最后一个“\”后面的路径
basename命令用于打印目录或者文件的基本名称,显示最后的目录名或文件名
dirname /etc/httpd/ # 结果为/etc
dirname /etc/httpd/conf/httpd.conf #结果为 /etc/httpd/conf/
basename /etc/httpd/conf/httpd.conf # 结果为 httpd.conf
--------------------------------------------------------------------------------------------------------------
nohup
nohup rosbag record -O $bag_name --split --duration=30m -b 2048 $topic >/dev/null 2>&1 &
nohup 是 no hang up 的缩写,就是不挂断的意思。nohup命令:如果你正在运行一个进程,而且你觉得在退出帐户时该进程还不会结束,那么可以使用nohup命令。该命令可以在你退出帐户/关闭终端之后继续运行相应的进程。
nohup COMMAND & # 这样就能使命令永久的在后台执行
可参考 https://www.cnblogs.com/jinxiao-pu/p/9131057.html
date
date +"%Y%m%d_%H_%M_%S" # 时间格式:20200519_20_38_47
echo `date +"%Y%m%d_%H_%M_%S"` # 输出时间,必须加上``符号
date +"%T" # %T 时间(只含时分秒,小时以24小时制来表示)。
echo `date +"%T"`
%Y%m%d的参数可参考https://zhidao.baidu.com/question/484985079.html
a=date
$a 对
echo $a # date
a 错
b=`date`
$b 错
echo $b 对
b 对
查看文件(夹)权限
ls -ld /dev/shm/ 查看/dev/shm/目录(本身)的权限
ll /dev/shm/ 查看/dev/shm/目录下的文件(夹)的权限, 包括隐藏文件(夹)
ls -l /dev/shm/ 查看/dev/shm/目录下的文件(夹)的权限,不包括隐藏文件(夹)
``
### test
```c
# 如果 ls -ld /dev/shm/ | grep drwxrwxrwx的输出为空,就执行 chmod -R 777 /dev/shm/
if test -z "$(ls -ld /dev/shm/ | grep drwxrwxrwx)" ;then
chmod -R 777 /dev/shm/
fi
开机自启动数字小键盘numlock
# 如果该文件是可执行文件
if test -x /usr/bin/numlockx ; then
numlockx on
fi
chown 将指定文件的拥有者改为指定的用户或组
用户可以是用户名或者用户 ID,组可以是组名或者组 ID,文件是以空格分开的要改变权限的文件列表,支持通配符。
chown 需要超级用户 root 的权限才能执行此命令。
只有超级用户和属于组的文件所有者才能变更文件关联组。非超级用户如需要设置关联组可能需要使用 chgrp 命令。
chown mdc.mdc file(dir)
# 把file(或者目录)的拥有者和组都改为mdc用户
更多详细用法参考 https://www.runoob.com/linux/linux-comm-chown.html
判断文件夹是否存在,判断是不是一个文件
# 如果 /home/zhz/nas/abc目录不存在,则执行 mount
##### 注意文件或者目录需要用双引号
if [ ! -d “/home/zhz/nas/abc” ];then # 注意 [ 的右边有空格, ]的左边有空格.
mount -t nfs 192.168.1.163:/volume1_106/data /mnt/nas
else
echo “dir exists!”
fi
不使用[]的话也可以使用test命令
if test ! -d “/home/zhz/nas/abc” ;then
mount -t nfs 192.168.1.163:/volume1_106/data /mnt/nas
else
echo “dir exists!”
fi
# 如果 /home/zhz/nas/def.txt是一个文件,则执行
### 软链接不是文件,不能用-f来判断
if [ -f "/home/zhz/nas/def.txt" ];then
rm -f def.txt
fi
# 如果 /home/zhz/abc是一个链接文件,则执行
if [ -L "/home/zhz/abc" ];then
rm -f def.txt
fi
把一段命令当做变量输出
# 把命令用`()`括起来,然后在括号`()`前面加上`$`符号,最后把他们都用`" "`包起来即可.
"$(ls -ld /dev/shm/ | grep drwxrwxrwx)"
# 命令多重嵌套,先是 path_1 = dirname "${BASH_SOURCE[0],然后在 cd 到 $path_1,再执行 pwd显示当前路径,最后把他们当做变量赋值给 DIR
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
116.gdb调试和coredump
https://baijiahao.baidu.com/s?id=1599347824327158577&wfr=spider&for=pc
https://www.jianshu.com/p/e38a3f1cf7f7
https://www.pianshen.com/article/2260634841/
ulimit -c unlimited
#可以产生core且不受大小限制
sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t
#生成的core文件存放在/tmp目录下
几个常用的gdb命令:
bt
或where
可以定位到出现问题的函数
l(list)
显示源代码,并且可以看到对应的行号;
b(break)x
x是行号,表示在对应的行号位置设置断点;
p(print)x
x是变量名,表示打印变量x的值
r(run)
表示继续执行到断点的位置
n(next)
表示执行下一步
c(continue)
表示继续执行
q(quit)
表示退出gdb
117.ubuntu使用 nethogs 监测网络流量情况
最简单的安装方法: sudo apt-get install nethogs
,他会直接安装0.8.1版本/
安装成功后使用如下命令
``c
sudo nethogs
即可看到网络情况.
-----------------------------------------------
源码安装(没必要这么麻烦):
安装方法 参考 https://blog.csdn.net/Webster_WXH/article/details/77159766
最好是安装0.8.1版本,因为0.8.0有bug.
```c
sudo apt-get install build-essential
sudo apt-get install libncurses5-dev libpcap-dev
wget -c https://github.com/raboof/nethogs/archive/v0.8.1.tar.gz
tar xf v0.8.1.tar.gz
cd ./nethogs-0.8.1/
make && sudo make install
118.ubuntu定时执行脚本
如果发现/etc/crontab
中的定时任务没执行,可以使用/etc/init.d/cron status
来查看状态,可能会提示“Error: bad username; while reading /etc/crontab”等信息,这就是格式有错误,可能是空格和换行之类的错误。
详细可参考 https://www.cnblogs.com/kunpengit/p/4045343.html
ubuntu是cron
,别的平台可能是crond
可参考 https://www.cnblogs.com/lfri/p/10739602.html
service cron status
#查看服务状态
service cron start
#启动服务
service cron stop
#关闭服务
service cron restart
#重启服务
service cron reload
#重新载入配置
如果想要每2分钟执行一次a.sh
脚本的话,可以这么做:
对于需要使用root权限的命令,使用第一种方法即可.
方法1:
su root # 或者sudo su root
vim /etc/crontab
# 把下面这句话添加进去
# m h dom mon dow user command
*/2 * * * * root bash /home/zhz/a.sh
方法2:
su root # 或者sudo su root
crontab -e
# m h dom mon dow command #和第一种相比少了一个user
*/2 * * * * bash /home/zhz/a.sh
既可以定时几点几分执行脚本,也可以定时每分钟或每小时执行脚本
# m h dom mon dow user command
# 分钟 小时 DayOfMonth 月 DayOfWeek 用户 命令
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
28 6 * * * root bash /home/user/a.sh # 表示的是每天6:28分执行该脚本
1 * * * * root bash /home/user/a.sh # 表示的是每小时的第一分钟执行该脚本
*/1 * * * * root bash /home/user/a.sh # 表示的是每一分钟执行该脚本
119.修改ubuntu用户密码
下面这个命令可以直接修改密码,但是这个密码必须够长
passwd
下面这个方法可以只设置密码为1个字符,不限制长度
sudo passwd user_name
120.mdc安装和开启ftp服务
sudo apt-get install vsftpd # 安装ftp服务
servicenvsftpd start #启动ftp服务
service vsftpd status # 查看ftp服务状态,会看到 ACTIVE:active(running)
然后就可以使用ftp方式连接本服务器了。
如果是mdc服务器的话,这样会启动ftp服务失败,解决方案如下:
mdc上服务器的/etc/vsftpd.conf
文件和我们自己电脑的该文件都是默认有
listen=NO
listen_ipv6=YES
把mdc服务器上的/etc/vsftpd.conf
文件中的这两个参数值改为和自己电脑相反,即
listen=YES
listen_ipv6=NO
然后再
service vsftpd restart # 重启ftp服务
service vsftpd status # 查看ftp服务状态,会看到 ACTIVE:active(running)
ps -ef | grep ftp # 该命令会查到ftp服务vsftp和sftp服务,敲一遍就知道了
121.mdc启动网卡并设置其ip和子网掩码
ifconfig enp125s0f1 192.168.2.6 netmask 255.255.255.0 up
如果需要开机启动网卡并设置其ip和子网掩码,只需将他加入到/etc/rc.local
中即可。
122.LD_LIBRARY_PATH详解、C++静态库与动态库
(1) LD_LIBRARY_PATH详解
参考链接: https://www.jianshu.com/p/a62e1d327023
LD_LIBRARY_PATH中
的LD
是指的LOAD
LD_LIBRARY_PATH
是Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径。
可以使用 ls /usr/lib |grep lib
查看自己是否有需要的库文件,当然还需查看其它库文件目录:echo $LD_LIBRARY_PATH
里面一般可以看到七八个已经定义好的库文件搜索路径。
当执行函数动态链接.so时,如果此文件不在缺省目录下 /lib和/usr/lib
,那么就需要指定环境变量LD_LIBRARY_PATH
。
假如现在需要在已有的环境变量上添加新的路径名,则采用如下方式: LD_LIBRARY_PATH=NEWDIRS:$LD_LIBRARY_PATH
(newdirs是新的路径串), 实例如下;
export LD_LIBRARY_PATH=/export/apps/anaconda2/2.4.1/lib/:$LD_LIBRARY_PATH
每次使用某软件都需要临时修改库文件,因为上面的export方法是临时设置环境变量LD_LIBRARY_PATH
,重启或打开新的 Shell 之后,一切设置将不复存在。
可以将该 LD_LIBRARY_PATH
的 export
语句写到系统文件中,例如 ~/.bashrc
、/etc/profile
、/etc/export
或者 ~/.bash_profile
等等,取决于你正在使用的操作系统。
(2) C++静态库与动态库
C++静态库与动态库详细文档 参考 https://www.runoob.com/w3cnote/cpp-static-library-and-dynamic-library.html
ldd
命令可以查看一个动态链接库依赖的共享库,如
ldd /usr/lib/libmpi.so.12
命令,会打印出该动态库依赖的所有共享库:
linux-vdso.so.1 => (0x00007fff9bb5c000)
libibverbs.so.1 => /usr/lib/libibverbs.so.1 (0x00007fb509fb3000)
libopen-rte.so.12 => /usr/lib/libopen-rte.so.12 (0x00007fb509d39000)
libopen-pal.so.13 => /usr/lib/libopen-pal.so.13 (0x00007fb509a9c000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb50987f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb5094b5000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fb5092b1000)
libhwloc.so.5 => /usr/lib/x86_64-linux-gnu/libhwloc.so.5 (0x00007fb509077000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fb508e6f000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fb508c6c000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb50a498000)
libnuma.so.1 => /usr/lib/x86_64-linux-gnu/libnuma.so.1 (0x00007fb508a61000)
libltdl.so.7 => /usr/lib/x86_64-linux-gnu/libltdl.so.7 (0x00007fb508857000)
123.linux系统下查看本机所在局域网中所有设备IP
1. 安装arp-scan
sudo apt-get install arp-scan
2. 查看本机连接的局域网所用的网卡名称
执行ifconfig
命令查看网卡名称,如eth0、eth1、wlan0、wlan1、enp0s3
等等
3.运行 arp-scan
执行命令:
sudo arp-scan -I enp0s3 --localnet
124.linux抓包工具tcpdump的使用
linux可视化抓包工具可以使用wireshark,对于不能可视化的,还是得使用tcpdump
tcpdump -h
# 查看用法
最简单的用法: tcpdump -i eth0
过滤信息的方法:
抓取eth0网卡上的源主机为192.168.1.6
、协议为udp
、端口为22
的信息:
tcpdump -i eth0 src 192.168.1.6 udp port 22
抓取eth0网卡上的源主机为192.168.1.6
、协议为udp
、端口为22
的信息,并存进a.cap
文件中:
tcpdump -i eth0 src 192.168.1.6 udp port 22 -w a.cap
抓取eth0网卡上的目的主机为192.168.1.6
、协议为udp
、端口为22
的信息存进a.cap
文件中:
tcpdump -i 网卡名 dst 192.168.1.6 udp port 22 -w a.cap
tcpdump读取包a.cap
:
tcpdump -r a.cap
tcpdump读取包a.cap
中使用udp
协议,端口号是22
的数据 :
tcpdump -r a.cap udp port 22
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)