172. Makefile 模板
如何快速编译运行C/C++文件
如何快速编译运行C/C++文件
GDB小白专属
驼峰风格(CamelCase) 大小写字母混用,单词连在一起,不同单词间通过单词首字母大写来分开。 按连接后的首字母是否大写,又分: 大驼峰(UperCamelCase)和小驼峰(lowerCamelCase)
类型 | 命名风格 |
---|---|
类类型,结构体类型,枚举类型,联合体类型等类型定义, 作用域名称 | 大驼峰 |
函数(包括全局函数,作用域函数,成员函数) | 小驼峰 |
全局变量(包括全局和命名空间域下的变量,类静态变量),局部变量,函数参数,类、结构体和联合体中的成员变量 | 小驼峰 |
宏,常量(const),枚举值,goto 标签 | 全大写,下划线分割 |
注意: 上表中常量是指全局作用域、namespace域、类的静态成员域下,以 const或constexpr 修饰的基本数据类型、枚举、字符串类型的变量,不包括数组和其他类型变量。 上表中变量是指除常量定义以外的其他变量,均使用小驼峰风格。
我们推荐使用.h作为头文件的后缀,这样头文件可以直接兼容C和C++。 我们推荐使用.cpp作为实现文件的后缀,这样可以直接区分C++代码,而不是C代码。
目前业界还有一些其他的后缀的表示方法:
如果当前项目组使用了某种特定的后缀,那么可以继续使用,但是请保持风格统一。 但是对于本文档,我们默认使用.h和.cpp作为后缀。
C++的头文件和cpp文件名和类名保持一致,使用下划线小写风格。
如果有一个类叫DatabaseConnection,那么对应的文件名:
结构体,命名空间,枚举等定义的文件名类似。
函数命名统一使用小驼峰风格,一般采用动词或者动宾结构。
1 | class List { |
类型命名采用大驼峰命名风格。 所有类型命名——类、结构体、联合体、类型定义(typedef)、枚举——使用相同约定,例如:
1 | // classes, structs and unions |
对于命名空间的命名,建议使用大驼峰:
1 | // namespace |
除有明确的必要性,否则不要用 typedef/#define 对基本数据类型进行重定义。 优先使用<cstdint>
头文件中的基本类型:
有符号类型 | 无符号类型 | 描述 |
---|---|---|
int8_t | uint8_t | 宽度恰为8的有/无符号整数类型 |
int16_t | uint16_t | 宽度恰为16的有/无符号整数类型 |
int32_t | uint32_t | 宽度恰为32的有/无符号整数类型 |
int64_t | uint64_t | 宽度恰为64的有/无符号整数类型 |
intptr_t | uintptr_t | 足以保存指针的有/无符号整数类型 |
通用变量命名采用小驼峰,包括全局变量,函数形参,局部变量,成员变量。
1 | // Good: 推荐此风格 |
全局变量是应当尽量少使用的,使用时应特别注意,所以加上前缀用于视觉上的突出,促使开发人员对这些变量的使用更加小心。
1 | int g_activeConnectCount; |
1 | class Foo { |
对于struct/union的成员变量,仍采用小驼峰不加后缀的命名方式,与局部变量命名风格一致。
宏、枚举值采用全大写,下划线连接的格式。 全局作用域内,有名和匿名namespace内的 const 常量,类的静态成员常量,全大写,下划线连接;函数局部 const 常量和类的普通const成员变量,使用小驼峰命名风格。
1 | // 仅对宏命名举例,并不推荐用宏实现此类功能 |
仓鼠仓库
查看C/C++程序内存泄露的工具
C/C++多线程函数与使用
说明
:command
: 命令keyword
: 快捷键使用 vim 的内置帮助是一个好习惯(虽然很多朋友更喜欢在网上搜索相关的使用方法)。查看帮助的语法如下表格所示:
**前缀 ** | **例子 ** | **说明 ** |
---|---|---|
: |
:help :w |
有关 :w 命令的帮助 |
none |
:help j |
有关“j ”键在正常模式上下文中的帮助 |
v_ |
:help v_J |
有关在上下文中使用“J”键到视觉模式的帮助 |
i_ |
:help i_<Esc> |
有关在上下文中使用“Esc ”键插入模式的帮助 |
/ |
:help /\n |
有关搜索模式“\n ”的帮助 |
命令 | 说明 |
---|---|
:make |
内置命令编译项目 |
:cl |
显示编译错误信息 |
:cc + 数字 |
跳转编译错误位置 |
:cp/:cn |
向前/向后导航 |
copen |
打开 quickfix 窗口来查看编译信息 |
命令行上移动光标时最常用的键: C: ctrl; S: shift
命令 | 说明 |
---|---|
<Left> |
左移一个字符 |
<Right> |
右移一个字符 |
<S-Left> 或 <C-Left> |
左移一个单词 |
<S-Right> 或 <C-Right> |
右移一个单词 |
<C-B> 或 <Home> |
命令行行首 |
<C-E> 或 <End> |
命令行行尾 |
<C-W> |
删除光标前整个单词 |
<C-U> |
删除命令行上全部文字,从而让你从头开始。 |
注意
<S-Left>
(光标左移键和 Shift
键同时按下) 和 <C-Left>
(光标左移键和 Control
键同时按下) 并非在所有键盘上都有效。其它 Shift
和 Control
组合键也是这种情况。
在 vim 打开一个文件,在另一个地方修改了文件
:e
重新加载文件:e!
强制丢掉本地修改,从磁盘加载文件vim提供了自动加载的选项 autoread,默认关闭。
1 | :set autoread |
在vimrc中添加 set autoread即可打开自动加载选项,相关选项:
:help 'autoread'
:help timestamp
:help FileChangedShell
:help :checktime
另外,vim使用tag进行切换时,如果当前文件修改未保存,会提示需保存后才能跳转。
在vimrc中添加
1 | set autowriteall |
可使切换文件时,修改的文件被自动保存。
关闭文件再重新打开时,无法撤回历史动作。以下配置可以实现持久化undo记录
1 | set undofile |
二进制打开文件
1 | vim -b datafile |
vim 的
-b
选项是告诉vim打开的是一个二进制文件,不指定的话,会在后面加上0x0a
,即一个换行符
十六进制查看
1 | :%!xxd |
返回正常的格式:
1 | :%!xxd -r |
分组:
命令 | 说明 |
---|---|
:%!xxd -g 1 |
表示每1个字节为1组 |
:%!xxd -g 2 |
表示每2个字节为1组(默认) |
:%!xxd -g 4 |
表示每4个字节为1组 |
man xxd |
获得xxd的帮助文件 |
在编辑系统文件或者受权限保护的文件的时候,很容易会忘记在 vim 编辑之前添加 sudo,这样将会以只读模式打开文件,也就是编辑后不能保存。
但是这时候,你可能已经对文件做了一些修改(尚未保存),很显然,强制退出不是一个好选择。
非文件所有者保存时提示没有权限,为了避免丢失原有的改动,可以使用以下命令。其中实现原理也很简单,可以参考这里
1 | :w !sudo tee % |
键入此命令后,将要求您输入sudo命令的密码,然后文件就可以保存了。
注:我们应该使用 sudoedit 命令而不是 sudo vim 来编辑需要超级用户权限的文件。
我们将上述命令拆解来看下:
命令 | 说明 |
---|---|
:w |
这是写入命令。由于没有给出参数,vim 将把整个文件写入标准输出; |
!sudo |
将 sudo 命令作为 shell 命令而不是 vim 命令运行; |
tee |
tee命令用于读取标准输入并将其写入标准输出或文件; |
% |
vim 将其替换为您正在编辑的当前文件的名称。 |
:w
命令将整个文件写入 STDOUT(标准输出);然后,我们使用sudo命令(因为我们编辑的毕竟是一个系统文件)来获得临时权限。
百分号(%
)表示文件名,tee
命令从 STDOUT 获取 vim 的输出并将其写入 %
文件。
这基本上适用于 <Vim's STDOUT> | sudo tee /etc/ssh/sshd_config
,有点复杂…
快捷键 | 说明 |
---|---|
>> |
向右给它进当前行 |
<< |
向左缩进当前行 |
= |
缩进当前行 (和上面不一样的是,它会对齐缩进) |
=% |
把光标位置移到语句块的括号上,然后按=%,缩进整个语句块(%是括号匹配) |
G=gg 或gg=G |
缩进整个文件(G是到文件结尾,gg是到文件开头) |
我们都有过在互联网上复制代码的时候。当将代码粘贴到文件中时,缩进都给弄乱了,这时候需要怎样做呢?
为了避免这种情况,请在 .vimrc
文件中添加以下代码:
1 | set pastetoggle=<F2> |
对 vimrc 文件进行如上更改后,在粘贴代码之前按 F2 键,这样做将确保代码粘贴正确的缩进。
假设光标在第一行第一列,但是所要写的内容需要缩进,那在不按下制表符(tab
)和空格键的情况下,应该怎样做呢?
答案是在正常模式下按下 S
键。
当光标位于行的第一列时,按 Esc
键进入正常模式。然后按 S(大写
)键,这会将光标移动到适当的缩进深度,并自动进入“插入”模式,以便开始键入。
快捷键 | 说明 |
---|---|
Ctrl + O |
向后回退你的光标移动 |
Ctrl + I |
向前追赶你的光标移动 |
Ctrl + ^ |
跳转至先前编辑过的buffer |
我们可能遇到过这样的情况:我修改了这个文件,但是忘记都做了哪些修改了,并且我担心其中有些地方可能修改错了。
解决此问题的方法是查看缓冲区和文件之间的差异。可在 vim 中执行如下命令:
1 | :w !diff % - |
我们将上述命令拆解来看:
命令 | 说明 |
---|---|
:w |
用于保存/写入,在这个特定场景中,如果命令中没有指定文件名,则输出将写入STDIN(标准输入)文件; |
:!<command> |
是执行 shell 命令的语法,在这个例子中,我们在 shell 中运行 diff 命令; |
% |
表示未修改的当前文件的名称;试试这个::!echo % |
- |
是 diff 命令的 STDIN 文件。 |
因此,该命令首先将所有[未保存]
内容写入STDIN文件。然后diff
命令读取当前文件(%
)并将其与STDIN(-
)文件进行比较。
这个命令大致等同于这个shell命令:diff <original-file> <Vim's STDOUT>
我们应该都使用过 Microsoft word,其拼写检查器在拼写错误的单词下会有一条红色的波浪线。
vim 也内置了拼写检查器,但默认情况下是关闭的。我们可以使用如下命令启用它:
1 | :set spell |
这样,你可能会看到拼写错误的单词被突出显示,其突出显示的方式取决于你的 vim 颜色方案。我在拼写错误的单词下面有一条白色下划线,如下图所示:
要将这设置为 vim 的默认,可在 .vimrc 文件中添加如下配置:
1 | set spell |
默认情况下,我们使用 vim 打开文件,光标总会在第一行。在某些时候,我们希望光标能够定位在我们指定的某一行,而不是第一行。
可以通过使用 +n
(n为行号)选项来实现这一点,当然前提是你需要知道打开的文件总行数应大于或等于 n
,如下:
1 | vim +n <file-name> |
我们都知道,在正常模式(normal mode)下,可以使用 d
和 x
键删除文本,那么在插入模式下如何执行相同的操作(比如 dd
)呢?
以下是常用的一些方案:
快捷键 | 说明 |
---|---|
ctrl + w |
删除前一个单词(字)(相当于正常模式下的 db ) |
ctrl + h |
删除前一个字符 |
ctrl + u |
删除当前行所有前面的字符(相当于正常模式下的 d0 ) |
ctrl + k |
删除当前行中所有主要字符(相当于正常模式下的 d$ ) |
输入下面任一命令重载 ~/.vimrc
::so $MYVIMRC
或者 :source ~/.vimrc
:so[urce]! {file}
这个 vim 命令会从给定的文件比如 ~/.vimrc
读取配置。就像你输入的一样,这些命令是在普通模式下执行的。当你在 :global
、:argdo
、 :windo
、:bufdo
之后、循环中或者跟着另一个命令时,显示不会再在执行命令时更新。
命令 | 说明 |
---|---|
:He[xplore] |
把当前窗口上下分屏,并在下面进行目录浏览. (在下边分屏浏览目录) |
:He[xplore]! |
把当前窗口上下分屏,并在上面进行目录浏览. (在上边分屏浏览目录) |
:Ve[xplore] |
左右分屏(在左边分屏间浏览目录) |
:Ve[xplore]! |
左右分屏(在右边分屏间浏览目录) |
命令 | 说明 |
---|---|
:set scb |
让两个分屏中的文件同步移动, 要到需要同步移动的两个屏中都输入如下命令 (相当于使用“铁锁连环”) |
:set scb! |
需要解开,那么就输入下面的命令 |
注:
set scb
是set scrollbind
的简写
命令 | 说明 |
---|---|
:Te[xplorer] |
像Chrome这样的分页式的浏览 |
gt |
到下一个页 |
gT |
到前一个页 |
{i}gt |
i是数字,到指定页,比如:5 gt 就是到第5页 |
:tabm {n} |
切换Tab页 |
:tabs |
查看现在打开的窗口和Tab的情况 |
:tabclose |
[i] 如果后面指定了数字,那就关闭指定页,如果没有就关闭当前页 |
vim -p <files> |
如果你在Shell命令行下,你可以使用 vim 的 -p 参数来用Tab页的方式打开多个文件,如: vim -p *.cpp |
:bufdo tab split |
把buffer中的文件全转成Tab页 |
注意:区分大小写。另外,可以将底部的屏幕移动到右侧,实现上下分屏到左右分屏的转换。
命令/快捷键 | 说明 |
---|---|
:ls or :buffers |
查看缓冲区 |
:b[uffer] <n> :b[uffer] <filename> |
打开缓冲区n/<filename> |
:bn[ext] |
切换到下一个缓冲区 |
:bp[revious] |
切换到上一个缓冲区 |
:bl[ast] |
切换到最后一个缓冲区 |
:bf[irst] |
切换到最前一个缓冲区 |
buffer 标记说明
标记 | 说明 |
---|---|
– |
(非活动的缓冲区) |
a |
(当前被激活缓冲区) |
h |
(隐藏的缓冲区) |
% |
(当前的缓冲区) |
# |
(交换缓冲区) |
= |
(只读缓冲区) |
+ |
(已经更改的缓冲区) |
命令 | 说明 |
---|---|
:cope[n] |
打开quickfix |
:cw[indow] |
如果有错误, 则打开quickfix; 如果没有错误且quickfix开启, 则关闭quickfix |
:cp |
跳到上一个错误 |
:cn |
跳到下一个错误 |
:cl |
列出所有错误 |
:cc |
显示错误详细信息 |
快捷键 | 说明 |
---|---|
guu 或是 Vu |
把一行的文字变成全小写 |
gUU 或是 VU |
把一行的文件变成全大写 |
v |
进入选择模式,然后移动光标选择你要的文本, 按 u 转小写,按U 转大写 |
ga |
查看光标处字符的ascii码 |
g8 |
查看光标处字符的utf-8编码 |
gf |
打开光标处所指的文件 (这个命令在打到#include头文件时挺好用的,当然,仅限于有路径的) |
* 或 # |
在当前文件中搜索当前光标的单词 |
你是否在 Python、YAML等要求严格缩进格式的文件中遇到过问题?检查之后,发现文档的内容都是正确的,除了缩进,因为其中有一行是缩进了3个空格,而不是4个空格。
这种情况经常发生。大多数IDE允许我们查看特殊字符,并能识别行尾、空格和制表符。vim 不亚于其他任何IDE,它也可以显示那些隐藏的字符。
vim 中的隐藏字符可以被认为是“空格”。以下是 vim 为了更好的易读性而隐藏的字符:
字符 | 含义 |
---|---|
eol | 行尾(end of line) |
tab | |
trail | 换行符前的空格 |
extends | 最后一列中的字符,表示下一行是换行的延续 |
precedes | 第一列中的字符,表示此行是前一行的延续 |
conceal | |
nbsp | 空格字符 |
要临时显示隐藏字符,可使用如下命令:
1 | :set list |
临时显示隐藏字符后,如果想再次将隐藏字符隐藏,可使用如下命令:
1 | :set nolist |
如上图所示,启用 list 选项来显示隐藏字符后,文本区域会看到有 $
字符,表示换行符。
要 永久 显示换行符,可将如下命令添加到 vimrc 文件中:
1 | set list |
当打开隐藏字符的可见性时,vim有一个预先定义的字符集合,如上图所示,换行符由美元符号 $ 表示。
但是如果你不想要美元符号呢?如果你想要一个不同的字符来表示换行符呢?
以下是设置隐藏字符的一个例子:
1 | :set listchars=eol:^,tab:-,trail:!,extends:>,precedes:< |
上面的例子中,设置显示行尾(eol)的字符在 eol: 后面键入即可。
如上图所示,我复制了空格并将其粘贴在行尾,它们显示为感叹号 !
,同时,行尾字符由 $
变为了 ^
。
如果要永久使用上述设置,可将下面的命令添加到 vimrc 文件中:
1 | set listchars=eol:^,tab:-,trail:!,extends:>,precedes:< |
我们都喜欢使用制表符(tab)或者空格,但是,如果我们正在编辑的文本其缩进使用的符号正好与我们的习惯相反,该怎么办?
如果当前文件使用空格缩进文本,希望将它们转换为制表符时,需要运行如下两个 vim 命令:
1 | :set noexpandtab |
这样做会将所有空格转换为其等效的制表符。如果文档使用两个空格作为缩进宽度,它们将转换为1个制表符。如果 4 个空格用作单个缩进宽度时,这 4 个制表位将替换为 1 个制表字符。
如果要编辑的文件使用制表符缩进,并且要将制表符转换为空格,则需要运行如下4个 vim 命令:
1 | :set expandtab |
第一个命令(expandtab
)告诉 vim 使用空格展开 tab,第二个命令(tabstop
)设置使用多少个空格用作一个“缩进块”。
在我们的例子中,我们定义了“1个tab=4个空格”;当使用>>
运算符时,shiftwidth
命令用于控制缩进,这也被设置为4个空格。
最后,retab
命令将所有制表符(用于缩进)转换为空格。
先来看一个现实的问题,如果在 Vim 中,将正则表达式中定义的大量元字符原封不动地引用(就像 perl),势必会给使用正常编辑功能的人造成困扰。比如 /foo(1)
命令,按照正则表达式来理解会是搜索 foo1
字符串。而在大多数人编辑器中应该是搜索 foo(1)
字符串。
Vim 毕竟是一个编辑器,于是在 Vim 中规定,正则表达式的元字符必须用反斜杠进行转义(和大多数正则表达式对转义符的定义正好相反)。如果上面的例子要用正则表达式搜索,就应写成 /foo\(1\)
。但是,像 .
*
这种极其常用的元字符,都加上反斜杠就太麻烦了。而且,众口难调,有些人喜欢用正则表达式,有些人不喜欢用…
为了解决这个问题,Vim 设置了 magic 变量。简单地说,magic 就是设置哪些元字符要加反斜杠哪些不用加的。 简单来说:
magic (\m)
:除了 $ . * ^
之外其他元字符都要加反斜杠nomagic (\M)
:除了 $ ^
之外其他元字符都要加反斜杠这个设置也可以在正则表达式中通过 \m
\M
开关临时切换。 \m
后面的正则表达式会按照 magic 处理, \M
后面的正则表达式按照 nomagic 处理,并忽略实际的 magic 设置。
例如:
1 | /\m.* # 查找任意字符串 |
另外还有两个包含全部的命令。
\v
(即 very magic):任何元字符都不用加反斜杠\V
(即 very nomagic):任何元字符都必须加反斜杠例如:
1 | /\v(a.c){3}$ # 查找行尾的 abcaccadc |
Vim 默认设置是 magic,也推荐大家都使用 magic 的设置。有特殊需求时,直接通过 \v \m \M \V
中的一种定义即可。
Vim 中设定 magic 变量:
1 | :set magic " 设置magic |
本文下面使用的字符都是默认(magic)模式下的,在其他模式下请自行转义。
元字符 | 意义 |
---|---|
. |
匹配任意一个字符 |
[abc] |
匹配方括号中的任意一个字符。也可以用 - 表示范围 |
[a-z0-9] |
匹配小写字母和阿拉伯数字中的一个字符 |
[^abc] |
匹配除方括号中字符之外的任意一个字符 |
\(abc\) |
分组匹配,将 abc 放入 1 中 |
\d |
匹配阿拉伯数字,等同于 [0-9] |
\D |
匹配阿拉伯数字之外的任意字符,等同于 [^0-9] |
\x |
匹配十六进制数字,等同于 [0-9A-Fa-f] |
\w |
匹配单词字母,等同于 [0-9A-Za-z_] |
\W |
匹配除单词字母之外的任意字符,等同于 [^0-9A-Za-z_] |
\t |
匹配 <TAB> 字符 |
\s |
匹配空白字符,等同于 [ \t] |
\S |
匹配非空白字符,等同于 [^ \t] |
\a |
匹配所有的字母字符。等同于 [a-zA-Z] |
\l |
匹配小写字母 [a-z] |
\L |
匹配非小写字母 [^a-z] |
\u |
匹配大写字母 [A-Z] |
\U |
匹配非大写字幕 [^A-Z] |
注解
用
\(
和\)
进行分组匹配,在分组后面可以使用\1
、\2
等变量来访问分组的内容(注意:\0
表示匹配的所有内容),最多保存一行中的 9 个分组。这种形式实际上是将分组中的内容保存到特殊的空间(保留缓冲区)中。
1
2
3
4 # 原字符串 That or this
# 替换后的字符串 this or That
:%s/\(That\) or \(this\)/\2 or \1/
元字符 | 意义 |
---|---|
* |
匹配 0 个或多个 |
\+ |
匹配1个或多个(匹配优先) |
\? 或 \= |
0 个或 1 个,\? 不能在 ? 命令中使用 |
\{n,m} |
匹配 n 个到 m 个 |
\{n,} |
匹配最少 n 个 |
\{,m} |
匹配最多 m 个 |
\{n} |
匹配 n 个 |
注解
用于限定数量的元字符不仅可用于字符,也可以用于分组等模式。举例如下:
1 \(123\)\{2} # 匹配 123123
元字符 | 意义 |
---|---|
$ |
匹配行尾,如 tail$ 只匹配位于一行结尾处的 tail |
^ |
匹配行首,如 ^head 只匹配位于一行开头处的 head |
\< |
匹配以某些字符开头的单词,\<ac 只匹配以 ac 开头的单词,如 action |
\> |
匹配以某些字符结尾的单词,ad\> 只匹配以 ac 开头的单词,如 head |
正则表达式中有贪婪匹配和非贪婪匹配两种,Vim 默认开启贪婪匹配。如果想使用非贪婪匹配,可以使用 \{-}
代替 *
、 +
等量词。
1 | 字符串:ahdbjkbkls |
替换markdown文件中代码块的代码语言
1 | :'<,'>s/^```\s*\(\n^\S\+\)/```bash\1/g |
将蛇形风格转化为小驼峰
%s!\(\<\|_\)\([a-z]\)!\U\2!g
path设置的目的是为了查找文件,比如说你使用gf指令打不开文件时,就得看看path是否设置正确了
1 | :help path |
默认的path包含:
.
表示,,
表示working directory不同于path。path表示查找文件的路径,working directory表示vim的工作路径,往往是打开vim的当前路径。在新建文件,或者打开文件时,会在working directory下操作。
working directory会被默认加到path中,即,,
用两个逗号表示
1 | //查看working directory |
查看错误信息 当Vim出现问题时,它通常会显示一些错误信息,可以通过查看这些信息来了解问题的具体原因。在Vim中,您可以使用:messages
命令来查看最近的错误和警告信息。
1 | :messages |
有时其他 Vim 配置可能会影响 t_SI 的行为。确保没有其他设置覆盖或修改了 t_SI 的设置。您可以通过执行 :verbose set t_SI?
命令来查看最后一次设置 t_SI 的地方,并检查是否有其他配置可能会干扰它。
1 | :verbose set t_SI? |
1 | :[count]verb[ose] {command} |
执行命令 {command},执行期间 ‘verbose’ 设为 [count]。 如果忽略 [count],缺省为 1。”:0verbose” 可以用来设置 ‘verbose’ 为零。
在此基础之上再应用 “:silent”,可以产生相应详细度的消息但不显示。”:silent” 和 “:verbose” 的组合因而可以只在内 部产生消息,然后用 v:statusmsg 或相关命令进行检查。
例如:
1 | :let v:statusmsg = "" |
如果和别的命令相连接,”:verbose” 只适用于第一个命令:
1 | :4verbose set verbose | set verbose |
verbose=4
verbose=0
要记录 verbose 消息到文件,用 ‘verbosefile’ 选项。
具体见这里
检查Vim配置文件 如果您在Vim中添加了自定义配置,那么这些配置可能会导致一些问题。要解决这些问题,您可以尝试禁用配置并逐个重新启用来找到问题所在。您可以使用 :scriptnames
命令查看当前加载的所有脚本,并使用 :scriptname
命令检查特定的脚本。
1 | :scriptname |
检查运行环境 如果您在Vim中使用外部命令或脚本,那么运行环境可能会导致一些问题。例如,某些命令或脚本可能需要特定的环境变量或依赖项。您可以使用 :! echo $PATH
命令查看当前环境变量,并使用:! 命令执行外部命令。
:redir > filename
命令,其中 filename
是您要保存输出的文件名。:redir END
来停止重定向。Linux 命令是使用终端与系统交互的好方法。但是,有时可能需要一段时间才能完成手头的任务。这迫使用户等待相当长的时间或完全生成一个新的 shell。
幸运的是,您可以通过一些简单的方法在后台运行 Linux 命令。
在你的命令后添加一个 &
运行 Linux 后台命令的最简单方法是在命令后添加与号 (&
)。例如,如果从终端启动 gedit 文本编辑器,则在关闭编辑器之前无法使用 shell。但是,当您在命令中添加额外的 & 时,您将能够立即使用 shell。
1 | $ gedit & |
对于需要长时间执行的任务,&
符号可以使当前终端窗口不被占用,这样就能继续在同一个终端上工作,甚至关闭终端窗口也不会影响任务的正常执行。不过需要注意的是,如果要求这个任务输出内容到标准输出中(例如 echo
或 ls
),即便使用了 &
,也会等待这些输出任务在前台运行完毕;当使用 &
将一个进程放置到后台运行的时候,Bash 会提示这个进程的进程 ID。在 Linux 系统中运行的每一个进程都有一个唯一的进程 ID,我们可以使用进程 ID 来暂停、恢复或者终止对应的进程。
Linux 中 的nohup命令允许管理员运行不受挂断(Hang Up)信号影响的终端命令。您可以使用 nohup 在后台运行 Linux 命令。
nohup 的一个主要好处是,即使您退出 shell,您的命令也会运行。此外,它会生成执行的日志文件。在当前目录或 $HOME
中查找nohup.out
。语法是:
1 | nohup 命令 |
如: 后台运行Nmap 端口扫描
1 | $ nohup sudo nmap -sS --top-ports=15 192.168.150.1/24 |
Q: Within zsh the command
&!
is a shortcut for disown, i.e. the program won’t get killed upon exiting the invoking shell.
程序退出不被杀死, 同时如果再次登录shell, 那么使用 ps -ef | grep "clash"
会显示clash 的父进程是 1
, 这是因为创建的父进程被杀死, 那么由该进程创建的子进程会在父进程被杀死后, 父进程改为 1
1 | nohup clash &> /dev/null &! |
程序退出会被杀死的进程
1 | nohup clash &> /dev/null & |
ctrl+z
以暂停这条命令并返回客户端bg
命令让这条shell命令在后台执行disown -h
这条命令保证当终端关闭时,Shell脚本不会被杀死ctrl+z将任务暂停,这时屏幕会打印这样一句 [1]+ Stopped ./myserver
使用 bg %1
将这个任务转入后台运行(1
是刚才暂停任务的job号,步骤1中屏幕提示方括号里面的内容,如果忘了也可以用 jobs
命令查看)
使用 disown –h %1
指定shell退出时不要发送SIGHUP给任务1(注意任务号前面有个%)
jobs
查看后台执行的命令fg %<d>
将 jobs[d] 切换到前台使用 disown 将 Linux 命令设置为后台运行
Linux 中 的disown
命令可以轻松地在后台运行命令。首先,您需要使用&
运算符在后台发送任务。然后,键入disown
以将其与shell分离。
1 | $ gedit & disown |
disown
的一个主要优点是,与 nohup 一样,当您关闭 shell 或注销时,系统不会终止您的任务。
使用 Tmux 在后台运行 Linux 命令
Tmux 是一个强大的多路复用器,它允许我们在单个窗口中运行多个终端会话。对于不熟悉它的人来说,学习 tmux 是一个很好的选择。Tmux 使在 Linux 中运行后台命令毫不费力。
1 | tmux new -d 'ping -c 10 8.8.8.8 > www.itpro.net.cn.log' |
当您运行上述tmux命令时,它将在单独的 shell 中执行ping命令并将其保留在后台。您可以使用此方法在后台执行任何 Linux 命令。
能够在后台运行命令使系统管理对管理员来说更有效率。您可以通过多种方式为您的任务做背景。像&和Ctrl + Z
这样的 Bash 功能很方便,但系统会在 shell 关闭时终止后台作业。另一方面,即使您注销或终止 shell ,诸如nohup
和disown
之类的工具也会使您的命令保持运行。
如果您将程序长时间留在后台,如果编码不当,它们可能会变成僵尸进程。这些过程会显着降低系统速度。因此,请确保每隔一段时间识别并杀死僵尸进程。
-n
是显示行号;相当于nl命令;例子如下:
tail -100f test.log
实时监控100行日志
tail -n 10 test.log
查询日志尾部最后10行的日志;
tail -n +10 test.log
查询10行之后的所有日志;
跟tail是相反的,tail是看后多少行日志;例子如下:
head -n 10 test.log
查询日志文件中的头10行日志;
head -n -10 test.log
查询日志文件除了最后10行的其他所有日志;
tac
是倒序查看,是cat
单词反写;例子如下:
cat -n test.log |grep "debug"
查询关键字的日志
按行号查看—过滤出关键字附近的日志
cat -n test.log |grep "debug"
得到关键日志的行号cat -n test.log |tail -n +92|head -n 20
选择关键字所在的中间一行. 然后查看这个关键字前10行和后10行的日志:tail -n +92
表示查询92行之后的日志head -n 20
则表示在前面的查询结果里再查前20条记录根据日期查询日志
sed -n '/2014-12-17 16:17:20/,/2014-12-17 16:17:36/p' test.log
特别说明:上面的两个日期必须是日志中打印出来的日志,否则无效;
先 grep '2014-12-17 16:17:20' test.log
来确定日志中是否有该 时间点
日志内容特别多,打印在屏幕上不方便查看
使用more和less命令,
如: cat -n test.log |grep "debug" |more
这样就分页打印了,通过点击空格键翻页
使用 >xxx.txt
将其保存到文件中,到时可以拉下这个文件分析
如:cat -n test.log |grep "debug" >debug.txt
颜色 | 文件类型标识 | 含义 |
---|---|---|
浅蓝色 | [l] |
软链接 |
白色 | [-] |
普通文件/硬链接 |
蓝色 | [d] |
目录 |
红色 | [l] |
某文件被删除后,链接到该文件的软链接的颜色 |
红色闪烁 | 无 | 表示该文件已被删除,但还存在该文件的软链接 |
红色 | [-] |
压缩包 |
黄色 | [c] |
字符设备文件,如键盘鼠标 |
绿色 | [-] |
可执行文件,可执行的程序 |
桃红色 | [s] |
套接字文件 |
土黄色 | [p] |
管道文件 |
灰色文件 | 无 | 表示其它文件 |
1 | netstat -tunlp |
用于显示 tcp,udp 的端口和进程等相关情况。
netstat 查看端口占用语法格式:
1 | netstat -tunlp | grep 端口号 |
例如查看 8000 端口的情况,使用以下命令:
1 | # netstat -tunlp | grep 8000 |
更多命令:
1 | netstat -ntlp //查看当前所有tcp端口 |
不建议使用: 因为每次启动shell都会启动, 而像clash这样的程序只需要执行一次即可, 并且如果多个用户执行, 会导致后执行clash的shell执行失败.
打开 ~/.bashrc
或 ./.zshrc
在文件末尾添加又在每次用户登录时执行的命令, 如
1 | nohup clash &> /dev/null & |
source ~/.bashrc
或 source ~/.zshrc
以使更改生效
(Startup Applications Preferences)
~/.config/autostart
目录中的 .desktop
文件中. 每个启动的应用程序都有一个相应的 .desktop
文件,该文件包含有关应用程序启动方式的信息。添加文件 vim <startup_program>.desktop
, 添加如下配置
1 | [Desktop Entry] |
如:
1 | Desktop Entry] |
Exec
行指定了要在启动时运行的程序的路径
采用systemctl的方式
强烈建议看看这个文档,里面介绍了一些参数的具体含义.
准备工作
写好脚本(假设脚本名为 exec_clash.sh)或将程序放入本地可以运行, 这里以clash为例, 其中, clash位于 /usr/local/bin/clash
exec_clash.sh 中的 exec_clash 是可根据具体脚本的功能改为相应的名字
若是脚本, 则赋予脚本运行权限: chmod +x exec_clash.sh
配置
编写一个 <clash>.service
, 内容如下:
1 | [Unit] |
说明
User
: 表示以哪个用户启动,不写默认是root. 而用户名也决定了程序启动去哪里读取相应的配置
ExecStart
: 就是要执行的语句。
由于为脚本赋予了x
(可执行)权限, 因此, ExecStart
后面的内容可以直接写成脚本的绝对路径
Restart=always
: 只要不是通过systemctl stop
来停止服务,任何情况下都必须要重启服务,默认值为no。还可以配置有条件重启,具体参考上述文档。
RestartSec=5
: 重启间隔,比如某次异常后,等待5(s)再进行启动,默认值0.1(s)
StartLimitInterval
: 无限次重启,默认是10秒内如果重启超过5次则不再重启,设置为0表示不限次数重启
拷贝 clash.service
到 /lib/systemd/system
, 需要注意权限问题
修改配置文件后需要重加载配置: sudo systemctl daemon-reload
设置开机自启: sudo systemctl enable clash.service
之后就可以直接重启了
相关操作
操作 | 命令 |
---|---|
启动 | sudo systemctl start clash.service |
停止 | sudo systemctl stop clash.service |
查看状态 | sudo systemctl status clash.service |
测试自动重启功能
大多数默认应用程序将具有位于/usr/share/applications
中的.desktop
文件。
要了解在启动其中一个应用程序时将运行的相应终端命令,请打开文件浏览器Nautilus,然后右键单击应用程序的图标以在上下文菜单中选择“属性”。这将为您提供所需的所有详细信息(此处显示将运行gnome-control-center -overview
的系统设置)
如果通过存储库或dpkg安装了应用程序,则可以使用以下命令:
1 | dpkg -l | grep "<application name>" |
这将搜索所有已安装的应用程序,并搜索其描述;搜索描述是这里的重要部分,因为描述通常包含应用程序的名称,即使运行它的”command”不包含应用程序名称。
例:
在GNOME中,有一个名为Disk Usage Analyzer的应用程序。但是,从终端运行它的命令不是disk-usage-analyzer。要查找其命令,您可以运行:
1 | dpkg -l | grep "disk usage" |
输出应包含此条目:
1 | alaa@aa-lu:~$ dpkg -l | grep "disk usage" |
看第二栏。实际运行磁盘使用率分析器的命令是baobab
。
参考目录
1 | mv * .[^.]* <destination_directory> |
解释
1、mv命令的最后一个参数是要移动文件的目标位置;
2、第一个 *
匹配除了隐藏文件的所有文件;
3、隐藏文件使用 .[^.]*
匹配
4、匹配隐藏文件用 .[^.]*
为什么不用 .*
: .*
会匹配目录 .
和 ..
5、.[^.]*
的意思是:以 .
开头,加不是 .
的一个任意字符,再加其他任意字符
参数补充
参数说明:
参数 | 说明 |
---|---|
-b |
当目标文件或目录存在时,在执行覆盖前,会为其创建一个备份。 |
-i |
如果指定移动的源目录或文件与目标的目录或文件同名,则会先询问是否覆盖旧文件,输入 y 表示直接覆盖,输入 n 表示取消该操作。 |
-f |
如果指定移动的源目录或文件与目标的目录或文件同名,不会询问,直接覆盖旧文件。 |
-n |
不要覆盖任何已存在的文件或目录。 |
-u |
当源文件比目标文件新或者目标文件不存在时,才执行移动操作。 |
首先,阅读Clash的API的文档RESTful - Proxies
GET
获取所有代理
1 | /proxies |
PUT
切换 Selector 中选中的代理
1 | /proxies/<name> |
(这边的name
可以为节点名称,也可以为Selector。只要在proxies/
后直接加上字符串就可以,不需要引号或者:
)
当前接口只支持切换 Selector 中的代理
Path Parameters | Body Parameters |
---|---|
name |
name |
string |
string |
代理Selector名称(大小写敏感) | 要切换的代理名字 |
接着,curl
使用指南 curl 的用法指南
最后,使用curl
切换节点, 使用/proxies
获取所有可用代理,然后curl
发送PUT请求解决战斗。
1 | curl -X PUT -H "Content-Type: application/json" -d '{"name":"节点名"}' http://localhost:port/proxies/<name> |
-H
添加 HTTP 请求的标头Content-Type: application/json
,根据链接2,不设置标头为application/json
可能会有问题。
-d
参数用于发送 POST 请求的数据体。
最后的网址为clash的external-controller
的网址端口,最后Selector为要选择的proxy-groups
的名称。
实际指令类似下面这条:
获取命令
1 | curl -X GET -H "Content-Type: application/json" http://127.0.0.1:9090/proxies -o get.json |
更改节点
1 | curl -X PUT -H "Content-Type: application/json" -d '{"name":"香港-08"}' http://127.0.0.1:9090/proxies/国外流量 -o put.json |
所有命令
1 | curl -X PUT -H "Content-Type: application/json" -d '{"name":"香港-08"}' http://127.0.0.1:9090/proxies/国外流量 -o put.json |
reference: sakronos