0%

  1. 重启ubuntu,随即长按shirft进入grub菜单;
  2. 选择recovery mode,按”e”键进入编辑页面;
  3. 将ro single替换为rw single init=/bin/bash;
  4. 按ctrl+x进入单用户模式,当前用户即为root;
  5. 到/etc目录下修改sudoers权限:chmod 0440 sudoers,搞定;
  6. 按ctrl+alt+del重启;

指定目录的定位 whereis

.. note::

你在哪里,哪里就是风景。

Linux whereis 命令用于定位查找一个命令的二进制、源文件或帮助文件。

不过这些文件一般是位于特定目录的。

其他的程序定位可以考虑使用locate命令。

官方的定义为:

whereis - locate the binary, source, and manual page files for a command

使用语法

使用语法如下:

1
$ whereis [options] [-BMS directory... -f] name...

其他的选项可以为:

  • -b : 查找二进制文件

  • -m:查找手册

  • -s:查找源文件

  • -B <directory>  在设置的目录下查找二进制文件。

  • -M <directory>  在设置的目录下查找说明文件。

  • -S <directory>  在设置的目录下查找原始代码文件。

实例

比如查找bash的位置,输入如下命令:

1
2
$ whereis bash
bash: /usr/bin/bash /etc/bash.bashrc /usr/share/man/man1/bash.1.gz

可以看到,以上的输出信息从左至右分别为程序名、bash路径、bash的man帮助手册路径。

单独查找文件

可以通过不同的参数来查找不同的文件,如下:

1
2
3
4
5
6
7
8
9
10
11
# 查找二进制文件
$ whereis -b bash
bash: /usr/bin/bash /etc/bash.bashrc

# 查找帮助文件
$ whereis -m bash
bash: /usr/share/man/man1/bash.1.gz

# 查找源文件
$ whereis -s bash
bash:

Markdown 格式集锦

$Markdown$ 由亚伦·斯沃茨此处有掌声(Aaron Hillel Swartz;1986年11月8日-2013年1月11日)和美国著名博客作者约翰·格鲁伯(John Gruber)合作发明了。

$Markdown$格式主要在程序员间流行,自从自己入了git的坑,就喜欢上了简洁明了的语法,除非特殊需要,已经不在接触Office系列了。^_^

这里主要列举一些$Markdown$的语法,其实只要掌握几个就能用的相当遛了。

内容目录测试

只需要加入[TOC]就可以看到内容目录了。

标题

标题共有6级,从最大的第1级到第6级,是几级就加几个#即可。

1
2
3
4
5
6
# 标题1
## 标题2
### 标题3
#### 标题4
##### 标题5
###### 标题6

输出为:

标题1

标题2

标题3

标题4

标题5
标题6

引用

linux dos2unix命令

有时碰到unix换行符转换为windows换行符的问题,特别是脚本,会报错syntax error near unexpected token `$’in\r’’,需要使用dos2unix命令将文件转换为unix格式。

dos2unix命令用来将DOS格式的文本文件转换成UNIX格式的(DOS/MAC to UNIX text file format converter)。DOS下的文本文件是以\r\n作为断行标志的,表示成十六进制就是0D 0A。而Unix下的文本文件是以\n作为断行标志的,表示成十六进制就是0A。DOS格式的文本文件在Linux底下,用较低版本的vi打开时行尾会显示^M,而且很多命令都无法很好的处理这种格式的文件,如果是个shell脚本,。而Unix格式的文本文件在Windows下用Notepad打开时会拼在一起显示。因此产生了两种格式文件相互转换的需求,对应的将UNIX格式文本文件转成成DOS格式的是unix2dos命令。

1
dos2unix [-hkqV] [-c convmode] [-o file ...] [-n infile outfile ...]

选项

1
2
3
4
5
6
1. -k:保持输出文件的日期不变 
2. -q:安静模式,不提示任何警告信息
3. -V:查看版本
4. -c:转换模式,模式有:ASCII, 7bit, ISO, Mac, 默认是:ASCII
5. -o:写入到源文件
6. -n:写入到新文件

最简单的用法就是dos2unix直接跟上文件名:

1
dos2unix filename

如果一次转换多个文件,把这些文件名直接跟在dos2unix之后。(注:也可以加上-o参数,也可以不加,效果一样)

1
2
dos2unix filename1 filename2 filename3 
dos2unix -o filename1 filename2 filename3

上面在转换时,都会直接在原来的文件上修改,如果想把转换的结果保存在别的文件,而源文件不变,则可以使用-n参数。

1
dos2unix oldfilename newfilename 

如果要保持文件时间戳不变,加上-k参数。所以上面几条命令都是可以加上-k参数来保持文件时间戳的。

1
2
3
4
dos2unix -k filename
dos2unix -k filename1 filename2 filename3
dos2unix -k -o filename1 filename2 filename3
dos2unix -k -n oldfilename newfilename

C语言中static的作用

隐藏

当我们同时编译多个文件时,所有未加 static 前缀的全局变量和函数都具有全局可见性。
为理解这句话,我举例来说明。我们要同时编译两个源文件,一个是 sub.c,另一个是 main.c。

下面是 sub.c 的内容:

sub.c 文件代码

1
2
3
4
5
char a = 'A'; // global variable
void msg()
{
printf("Hello World\n");
}

下面是 main.c 的内容:

main.c 文件代码

1
2
3
4
5
6
7
int main(void)
{
extern char a; // extern variable must be declared before use
printf("%c ", a);
(void)msg();
return 0;
}

程序的运行结果是:

1
A Hello World

在 sub.c 中定义的全局变量 a 和函数 msg 能在 main.c 中使用是因为所有未加 static 前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。
如果加了 static,就会对其它源文件隐藏。例如在 a 和 msg 的定义前加上 static,main.c 就看不到它们了。
利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。

static 可以用作函数和变量的前缀,对于函数来讲,static 的作用仅限于隐藏,而对于变量,static 还有下面两个作用。

static 的第二个作用是保持变量内容的持久。

存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和 static 变量,只不过和全局变量比起来,static 可以控制变量的可见范围,说到底 static 还是用来隐藏的。虽然这种用法不常见,但我还是举一个例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int fun(void){
static int count = 10; // 事实上此赋值语句从来没有执行过
return count--;
}

int count = 1;

int main(void)
{
printf("global\t\tlocal static\n");
for(; count <= 10; ++count)
printf("%d\t\t%d\n", count, fun());

return 0;
}

程序的运行结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
global          local static

1 10

2 9

3 8

4 7

5 6

6 5

7 4

8 3

9 2

10 1

static 的第三个作用是默认初始化为 0

其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是 0x00,某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵,我们可以一个一个地把所有元素都置 0,然后把不是 0 的几个元素赋值。如果定义成静态的,就省去了一开始置 0 的操作。再比如要把一个字符数组当字符串来用,但又觉得每次在字符数组末尾加 \0 太麻烦。如果把字符串定义成静态的,就省去了这个麻烦,因为那里本来就是 \0 。

不妨做个小实验验证一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

int a;

int main(void)
{
int i;
static char str[10];

printf("integer: %d; string: (begin)%s(end)", a, str);

return 0;
}

程序的运行结果如下:

1
integer: 0; string: (begin)(end)

最后对 static 的三条作用做一句话总结。首先 static 的最主要功能是隐藏,其次因为 static 变量存放在静态存储区,所以它具备持久性和默认值0。

活灵活现的终端:发掘cowsay

cowsay顾名思义就是一头牛为你加持,一款让命令行界面生动有趣的工具。

cowsay 可说话、可思考,与fortune加持更可以变为一头睿智的牛。

该命令接受一个文本字符串,并输出一个牛说话的图形。

下面是一头牛在说它喜欢 Linux:

1
2
3
4
5
6
7
8
9
$  cowsay I love linux.
_______________
< I love linux. >
---------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

长着古怪眼睛的牛

1
2
3
4
5
6
7
8
9
$  cowsay -e @@ I love linux.         
_______________
< I love linux. >
---------------
\ ^__^
\ (@@)\_______
(__)\ )\/\
||----w |
|| ||

伸出舌头的牛

1
2
3
4
5
6
7
8
9
$ cowsay -T U I love linux.
_______________
< I love linux. >
---------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
U ||----w |
|| ||

一头睿智的牛

一旦将fortune和cowsay结合起来,那简直是一头及其睿智的牛呀。

1
2
3
4
5
6
7
8
9
10
11
$ fortune | cowsay
__________________________________
/ 贤能不待次而举。 \
| |
\     - 荀况 /
----------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||

点亮终端的艺术之光figlet

在Linux的世界中,figlet是一个神奇的命令,可以将文字艺术化.

特别适合作为标题、口号或者问候语,还有很多软件程序的招呼语,也可以用这个来实现。

比如:

1
2
3
4
5
6
7
$ figlet HELLO          
_ _ _____ _ _ ___
| | | | ____| | | | / _ \
| |_| | _| | | | | | | | |
| _ | |___| |___| |__| |_| |
|_| |_|_____|_____|_____\___/

显示系统风貌的screenfetch命令

screenfetch命令的神奇之处在于其简单而又直观的功能,该命令能够快速地收集系统信息并以一种富有个性的方式展示出来。

从使用的发行版到内核版本,再到处理器和内存,一目了然地展现系统的全貌。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ screenfetch
./+o+- oper@localhost
yyyyy- -yyyyyy+ OS: Ubuntu
://+//////-yyyyyyo Kernel: aarch64 Linux 6.4.16-linuxkit
.++ .:/++++++/-.+sss/` Uptime: 33m
.:++o: /++++++++/:--:/- Packages: 134
o:+o+:++.`..```.-/oo+++++/ Shell: bash 5.1.16
.:+o:+o/. `+sssoo+/ Disk: 32G / 59G (57%)
.++/+:+oo+o:` /sssooo. CPU: 12x Apple
/+++//+:`oo+o /::--:. RAM: 877MiB / 7844MiB
\+/+o+++`o++o ++////.
.++.o+++oo+:` /dddhhh.
.+.o+oo:. `oddhhhh+
\+.++o+o``-````.:ohdhhhhh+
`:o+++ `ohhhhhhhhyo++os:
.o:`.syhhhhhhh/.oo++o`
/osyyyyyyo++ooo+++/
````` +oo+++o\:
`oo++.

放开了去的 ulimit

.. note::
离离原上草,一岁一枯荣。
白居易《草 / 赋得古原草送别》

ulimit简介

对于高并发或者频繁读写文件的应用程序而言,有时可能需要修改系统能够打开的最多文件句柄数,否则就可能会出现too many open files的错误。

而句柄数分为系统总限制和单进程限制。可以使用ulimit -n来查看系统对单个进程的限制及可以打开的文件数目。

或者执行ulimit -a来查看所有的详细信息。

临时修改打开文件数目

对于临时的修改而言,可以终端中输入下面的命令,将该值调整为65536.

1
$ ulimit -HSn 65535

上面的命令将open files修改为65535,不过退出当前shell后即失效。
H和S分别表示硬限制和软限制

永久修改

如果希望永久修改,需要修改配置文件 /etc/security/limits.conf,修改后需要重新启动系统。

1
2
* soft nofile 65535
* hard nofile 65535

其中的*表示所有的用户,softhard分别表示软硬限制,nofile表示能够打开的最大文件数,第四列为具体的值。其中具体的值有一个上次,在文件/proc/sys/fs/nr_open,默认为1048576,完全够用了。

系统总打开句柄限制

上面讨论的均为单个线程的限制,属于线程级别的,系统级别的限制在文件/proc/sys/fs/file-max文件中。

修改这个文件也是临时生效的,重启失效,如果希望永久生效,需要修改下面文件:
/etc/sysctl.conf

可以添加下面这行

1
fs.file-max = 6815744

然后运行sysctl -p或者重启生效。可以通过lsof -p PID 来查看单个进程打开的文件句柄

Linux对打开文件数量的限制 ulimit

对于高并发或者频繁读写文件的应用而言,需求修改系统能够打开的文件句柄数,
否则会出现too many open files的错误。

而句柄数分为系统总限制和单进程限制。
可以使用ulimit -n来查看系统对单个进程的限制,及open files。

或者执行ulimit -a来查看所有的详细信息。

临时修改打开文件数目

1
$ ulimit -HSn 65535

上面的命令将open files修改为65535,退出当前shell后即失效。
H和S分别表示硬限制和软限制

永久修改

如果希望永久修改,需要修改配置文件 /etc/security/limits.conf,修改后需要重新启动系统。

1
2
* soft nofile 65535
* hard nofile 65535

其中的*表示所有的用户,soft和hard分别表示软硬限制,nofile表示能够打开的最大文件数,第四列为具体的值。
其中具体的值有一个上次,在文件/proc/sys/fs/nr_open,默认为1048576,完全够用了。

系统总打开句柄限制

上面讨论的均为单个线程的限制,属于线程级别的,系统级别的限制在文件/proc/sys/fs/file-max文件中。

修改这个文件也是临时生效的,重启失效,如果希望永久生效,需要修改下面文件:
/etc/sysctl.conf

可以添加下面这行

1
fs.file-max = 6815744

然后运行sysctl -p或者重启生效。

可以通过lsof -p PID 来查看单个进程打开的文件句柄