0%

删除Linux多余内核

还记得曾经一度有个牛人,几百个大大的linux启动项列表,据说从头到尾看一遍就需要10几分钟,哥有洁癖,内核升级完后,如果使用稳定,过个几天就会清理掉(因为有时在安装新系统的时候可能boot分的不是很大,在update的时候,老是提示说boot分区大小不够,清理掉就瞬间OK了),不过最近的grub做的比较人性了,以前都是满屏的内核版本,现在除了最新的,其他的都放在一个Previous Linux Version了,就像微信里面的公众号放到一个文件夹里面,世界瞬间安静了很多。

Debian系列–适用于Ubuntu、LinuxMint等

第一种方法

找出系统已经安装的内核版本,在终端里输入命令:

1
dpkgget-selections | grep linux-image

然后会显示系统中已安装的内核.

卸载旧的内核版本,在终端里输入命令:

1
sudo apt-get remove linux-image-***

注意不要把最新的内核给删除掉哟,我没有测试过,不知道会出现嘛情况,你可以手一哆嗦小试一下撒。

删除内核后,运行下属命令,直接重启也可以。

1
update-grub

第二种方法

在图像界面下,可以使用新立得软件包管理器删除

  1. 点菜单“系统-系统管理-新立得软件包管理器”;
  2. 以2.6.32-21版本的内核为例,内核文件里包括:linux-headers-2.6.32-21、linux-headers- 2.6.32-21-generic、linux-image-2.6.32-21-generic、linux-restricted-modules-2.6.32-21-generic、linux-ubuntu-modules-2.6.32-21-generic;
  3. 在新立得中,点工具栏上的“搜索”按钮,在出来的搜索框中输入 linux 2.6.32-21 ,注意linux后面有一个空格

Redhat系列–适用于CentOS、Fedora等

第一种方法

首先列出系统中正在使用的内核:

1
# uname -a

查询系统中全部的内核:

1
# rpm -qa | grep kernel

将你想删除的内核删除掉🙁例如,在我的系统中,我要删掉kernel-2.6.32-279.9.1.el6.x86_64的内核,需要把所有含有kernel-2.6.32-279.9.1.el6.x86_64字样的全部删掉)

1
#yum remove kernel-2.6.32-279.9.1.el6.x86_64

重启后就可以看到,内核被删掉了,同时多余的启动项也自动被删掉了。

第二种方法

手动修改/boot/grub/menu.lst 把多余的项删除,但是这个指标不治本哟。

第三种方法 – 力荐

查看已经安装的内核命令:

1
rpm -q kernel

删除旧的内核

安装yum-utls:

1
sudo install yum-utils

设置你想要保留多少旧的内核,比如我想保留两个:

1
sudo package-cleanup –oldkernels –count=2

设置永久的内核安装数量,我设置的是两个

1
2
3
sudo gedit /etc/yum.conf
#设置
installonly_limit=2

重启,就只会看见两个内核启动项了。

第四种方法

删除除当前内核外的其他所有内核,一条命令即可解决:

1
yum remove kernel

recv/recvfrom/recvmsg系统调用

功能描述:

从套接字上接收一个消息。对于recvfrom 和 recvmsg,可同时应用于面向连接的和无连接的套接字。recv一般只用在面向连接的套接字,几乎等同于recvfrom,只要将recvfrom的第五个参数设置NULL。
如果消息太大,无法完整存放在所提供的缓冲区,根据不同的套接字,多余的字节会丢弃。
假如套接字上没有消息可以读取,除了套接字已被设置为非阻塞模式,否则接收调用会等待消息的到来。

用法:

1
2
3
4
5
6
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sock, void *buf, size_t len, int flags);
ssize_t recvfrom(int sock, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen);
ssize_t recvmsg(int sock, struct msghdr *msg, int flags);

参数:
sock:索引将要从其接收数据的套接字。
buf:存放消息接收后的缓冲区。
len:buf所指缓冲区的容量。
flags:是以下一个或者多个标志的组合体,可通过or操作连在一起
MSG_DONTWAIT:操作不会被阻塞。
MSG_ERRQUEUE: 指示应该从套接字的错误队列上接收错误值,依据不同的协议,错误值以某种辅佐性消息的方式传递进来, 使用者应该提供足够大的缓冲区。导致错误的原封包通过msg_iovec作为一般的数据来传递。导致错误的数据报原目标地址作为msg_name被提供。 错误以sock_extended_err结构形态被使用,定义如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#define SO_EE_ORIGIN_NONE    0
#define SO_EE_ORIGIN_LOCAL 1
#define SO_EE_ORIGIN_ICMP 2
#define SO_EE_ORIGIN_ICMP6 3
struct sock_extended_err
{
u_int32_t ee_errno; /* error number */
u_int8_t ee_origin; /* where the error originated */
u_int8_t ee_type; /* type */
u_int8_t ee_code; /* code */
u_int8_t ee_pad;
u_int32_t ee_info; /* additional information */
u_int32_t ee_data; /* other data */
/* More data may follow */
};

MSG_PEEK:指示数据接收后,在接收队列中保留原数据,不将其删除,随后的读操作还可以接收相同的数据。
MSG_TRUNC:返回封包的实际长度,即使它比所提供的缓冲区更长, 只对packet套接字有效。
MSG_WAITALL:要求阻塞操作,直到请求得到完整的满足。然而,如果捕捉到信号,错误或者连接断开发生,或者下次被接收的数据类型不同,仍会返回少于请求量的数据。
MSG_EOR:指示记录的结束,返回的数据完成一个记录。
MSG_TRUNC:指明数据报尾部数据已被丢弃,因为它比所提供的缓冲区需要更多的空间。
MSG_CTRUNC:指明由于缓冲区空间不足,一些控制数据已被丢弃。
MSG_OOB:指示接收到out-of-band数据(即需要优先处理的数据)。
MSG_ERRQUEUE:指示除了来自套接字错误队列的错误外,没有接收到其它数据。
from:指向存放对端地址的区域,如果为NULL,不储存对端地址。
fromlen:作为入口参数,指向存放表示from最大容量的内存单元。作为出口参数,指向存放表示from实际长度的内存单元。
msg:指向存放进入消息头的内存缓冲,结构形态如下

1
2
3
4
5
6
7
8
9
struct msghdr {
void *msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
struct iovec *msg_iov; /* scatter/gather array */
size_t msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data, see below */
socklen_t msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};

可能用到的数据结构有

1
2
3
4
5
6
7
struct cmsghdr {
socklen_t cmsg_len; /* data byte count, including hdr */
int cmsg_level; /* originating protocol */
int cmsg_type; /* protocol-specific type */
/* followed by
u_char cmsg_data[]; */
};

返回说明:
成功执行时,返回接收到的字节数。另一端已关闭则返回0。失败返回-1,errno被设为以下的某个值
EAGAIN:套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
EBADF:sock不是有效的描述词
ECONNREFUSE:远程主机阻绝网络连接
EFAULT:内存空间访问出错
EINTR:操作被信号中断
EINVAL:参数无效
ENOMEM:内存不足
ENOTCONN:与面向连接关联的套接字尚未被连接上
ENOTSOCK:sock索引的不是套接字

c语言中如何判断文件是否存在

一般情况下,我们可以使用函数stat(), access() 和fopen()来检验文件是否存在,但是由于文件权限的问题,有时可能不像结果所言,可能不是因为文件不存在,而是没有打开的权限。

函数fopen

通常情况下使用fopen主要用于读写文件,而我们就可以在这个上面做文章,通过以只读r的模式打开,如果失败,就是文件不存在咯。

1
2
3
4
5
6
7
8
9
10
11
FILE *fp;

fp=fopen(“file.txt” , “r”);

if ( fp == NULL )

printf(“file not exist!”);

else

fcolse(fp);

也可以写个子函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//存在返回0,不存在返回1
int file_exist(FILE *fo)

{

if(fopen(fp)==NULL)

return 1;

else

return 0;

}

函数access

设计的子函数为:

1
2
3
4
int file_exists(char *filename)
{
return (access(filename, 0) == 0);
}

access(filename, 0)0 表示判断文件是否存在
finename 文件名称 ,mode 模式,共5种模式:

  • 0-检查文件是否存在
  • 1-检查文件是否可运行
  • 2-检查文件是否可写访问
  • 4-检查文件是否可读访问
  • 6-检查文件是否可读/写访问

注意,有的不适用数字表示,比如文件是否存在使用模式F_OK,类似的R_OK、W_OK和X_OK分别表示读写和可执行模式。

函数stat

stat函数可以获取文件的属性:

·表头文件: #include <sys/stat.h>

·函数定义: int stat(const char *file_name, struct stat *buf);

·函数说明: 通过文件名filename获取文件信息,并保存在buf所指的结构体stat中

·返回值: 执行成功则返回0,失败返回-1,错误代码存于errno(需要include <errno.h>)

因此如果文件存在,该函数将返回0,否则返回1。利用stat()函数来判断文件是否存在的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int cfileexists(const char* filename){

struct stat buffer;

int exist = stat(filename,&buffer);

if(exist == 0)

return 1;

else // -1

return 0;

}

函数lstat

与stat函数比较类似,除了在符号链接的时候有点小差别。

函数open

对比与fopen,我们也可以使用open来判断文件的存在与否。

Linux 技巧

快捷键

  • 搜索历史命令的快捷键:Ctrl + r
  • Ctrl + f– 向右移动一个字符,当然多数人用→
  • Ctrl + b– 向左移动一个字符, 多数人用←
  • ESC + f– 向右移动一个单词,MAC下建议用ALT + →
  • ESC + b– 向左移动一个单词,MAC下建议用ALT + ←
  • Ctrl + a– 跳到行首
  • Ctrl + e– 跳到行尾
  • Ctrl + d– 向右删除一个字符
  • Ctrl + h– 向左删除一个字符
  • Ctrl + u– 删除当前位置字符至行首(输入密码错误的时候多用下这个)
  • Ctrl + k– 删除当前位置字符至行尾
  • Ctrl + w– 删除从光标到当前单词开头
  • Ctrl + p– 上一个命令,也可以用↑
  • Ctrl + n– 下一个命令,也可以用↓
  • Ctrl + y– 插入最近删除的单词
  • Ctrl + c– 终止操作
  • Ctrl + d– 当前操作转到后台
  • Ctrl + l– 清屏 (有时候为了好看)

MacOSX 集锦

快捷键

  • ⌘ + Q = Quit
  • ⌘ + W = Close window
  • ⌘ + O = Open a file in your application
  • ⌘ + P = Print
  • ⌘ + C = Copy
  • ⌘ + V = Paste
  • ⌘ + X = Cut
  • ⌘ + S = Save
  • ⌘ + Z = Undo
  • ⌘ + A = Select All
  • ⌘ + Y or Space = Quicklook
  • ⌘ + Tab = Cycle through windows
  • ⌘ + ⇧+ 3 = Take fullscreen picture
  • ⌘ + ⇧ + 4 = Take selected area screenshot
  • ⌘ + ⇧ + 4 + Space = Take screenshot of window or menu
  • ⌥ + ⌘ + Escape = Bring up Force Quit window
  • ⌘ + Space = Spotlight search
  • ⌘ +``` (back tick) = Cycle through applications windows
  • ⌘ + . = Cancel operation
  • ⌘ + ⇧ + ? = Open help
  • ⌘ + I = Get Info
  • ⌘ + [ = Go backwards in history in Finder
  • ⌘ + ] = Go forwards in history in Finder
  • ⌘ + Up Arrow = Go to previous folder in hierarchy
  • ⌘ + Down Arrow = Open folder of file in Finder
  • ⌘ + ⌥ + T = Show hide Finder’s toolbar
  • ⌘ + Delete = Move item to Trash
  • ⌘ + ⇧ + Delete = Empty Trash
  • ⌘ + E = Eject disk
  • ⌘ + F = Find
  • ⌘ + G = Next result in Find option
  • ⌘ + H = Hide application
  • ⌘ + M = Minimize
  • ⌘ + N = New window
  • ⌘ + ⌥ + W = Close all windows
  • ⌘ + ⇧ + Z = Redo
  • ⌘ + ⇧ + H = Go to Home folder
  • ⌘ + ⇧ + D = Go to Desktop
  • ⌘ + ⇧ + C = Go to Computer
  • ⌘ + ⇧ + K = Go to Network
  • ⌘ + ⇧ + I = Go to iDisk
  • ⌘ + ⇧ + A = Go to Application
  • ⌘ + ⇧ + U = Go to Utilities
  • ⌘ + ⇧ + G = Go to folder
  • ⇧ + ⌘ + Q = Log out
  • ⇧ + ⌘ + ⌥ + Q = Log out immediately.
  • ⌘ + D = Duplicate in Finder
  • ⌘ + ⌥ + 8 = Turn on Voice Over
  • ⌘ + ⌥ + + = Zoom in (if turned on)
  • ⌘ + ⌥ + – =Zoom Out
  • ⌘ + ⌥ + D = Show/Hide Dock
  • ^ + Eject = Show shutdown dialog
  • ^ + ⌘ + Eject = Close all and restart
  • ⌥ + ⌘ + Eject = Sleep
  • ⌘ + Shift + F = Find file by name
  • ⌘ + R = Refresh widget

[TOC]

C++调用C函数

C++保留了一部分过程式语言的特点,但更重要的是C++是一种面向对象的程序设计语言,为了支持函数的重载,C++对全局函数的处理方式与C有明显的不同。下面会对C++的重载overload说明一下。

extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。

加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。

比如说你用C 开发了一个动态链接库,为了能够让C++语言也能够调用你的函数,你需要用extern "C"来强制编译器不要修改你的函数名。

通过例子来说明

标准头文件

1
2
3
4
5
6
7
8
#ifndef __TEST_H  /*防止该头文件被重复引用*/
#define __TEST_H


// some declaration


#endif /* __TEST_H */

这个头文件,对于标准的C程序是没有任何问题的,编译/链接/调用。

改进头文件

但是如果使用C++来调用上面的一些定义函数,就会出现undefined error,这就是由于C++函数重载的原因。

解决方法就是下面的头文件,使用extern "C"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef __TEST_H  /*防止该头文件被重复引用*/
#define __TEST_H

#ifdef __cplusplus //__cplusplus是cpp中自定义的一个宏
extern "C" { //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的
#endif

// some declaration

#ifdef __cplusplus
}
#endif

#endif /* __TEST_H */

extern “C”的含义

extern "C"代表两方面的意思,extern以及C,也就是说被其修饰的函数是可以被外部调用的,并且是C的函数定义。

C和C++的区别

由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。

比如,同一个函数

1
void add(int x,int y);

c编译后在符号库中的名字为_add,C++中为_add_int_int,可以看到C++中包含了函数名/函数参数数量及类型信息,这也是为什么C++能重载的原因。

如何打标签

标签tag主要是在完成了一个版本后,用于发布该版本。

相关的命令如下:

列出标签

1
2
$ git tag              # 打印出当前仓库的所有标签
$ git tag -l '1.0.*' # 搜索符合模式的标签

创建标签

git标签有两种类型:轻量标签附注标签,创建的方法如下所示:

1
2
$ git tag v1.0-light                 # 创建轻量标签,只有一个引用
$ git tag -a v1.0 -m 'Release 1.0' # 创建附注标签,是个独立对象

一般创建都建议是附注标签(虽然轻量标签没有很多参数),搞个引用没有多大意思。

创建附注标签时,参数aannotated的缩写,指定标签类型,后附标签名。参数m指定标签说明,说明信息会保存在标签对象中。

可以通过git show v1.0来看到标签信息和与之对应的提交信息。

补打标签

打标签不必要在head之上,也可在之前的版本上打,这需要你知道某个提交对象的校验和(通过git log获取)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ git log --pretty=oneline

15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme

# 如果此时希望在updated rankfile补打标签,可以通过
# git tag -a v0.1.1 校验和
$ git tag -a v0.1.1 9fceb02

签署标签

如果你有自己的私钥,可以使用GPG来签署标签,只要把-a改为-s即可,也就是signed的意思。

1
$ git tag -s v0.1.1 校验和

验证标签

可以使用

1
$ git tag -v [tag-name]

的方式来验证已经签署的标签,其中v的意思为verify,
此命令会调用GPG来验证签名,所以需要有签署者的公钥,存放在keyring中,才能验证。

后期加注标签

如果对早前的那一次提交忘记加注标签了,那么可以使用git log --pretty=oneline来查看提交的HASH ID,然后使用

git tag -a v1.1 HASH-ID

即可补上标签。

切换标签

切换标签与切换分支命令一样,是用checkout即可,比如:

1
$ git checkout v1.0.0    # 注意前提是版本存在,可以是用git tag先检查一下

删除标签

不需要或者误操作提交一个标签的时候,删除即可,使用的是delete的缩写

1
$ git tag -d v1.1.1

删除远程tag这么用:

1
2
3
$ git push origin --delete tagname
# 或者
$ git push origin :refs/tags/tagname

查看标签信息

用git show命令可以查看标签的版本信息:

1
$ git show v0.1.2

标签发布

一般情况下,git push 不会将tag提交到服务端,我们需要显式的操作,如下所示:

1
2
3
$ git push origin [tag-name]
$ git push origin v1.1.1 #发布版本v1.1.1
$ git push origin -tags #一次发布所有的tag版本

查看某个标签

1
2
3
$ git  tag   		#查看当前分支下的标签
$ git checkout v0.21 #此时会指向打v0.21标签时的代码状态,(但现在处于一个空的分支上)
$ cat test.txt #查看某个文件

XTerm

xterm包的简介

最古老最基础的X Window终端模拟包是xterm。xterm包是在X Window出现之初便已经存在了的,默认包含在大多数X Window包中。

XTerm是一个X Window System上的终端模拟器,用来提供多个独立的SHELL输入输出。

XTerm最先是Jim Gettys的学生Mark Vandevoorde在1984年夏天为VS100写的独立虚拟终端,当时X的开发刚刚开始。很快人们就发现它作为X的一部分比作为独立的程序更为有用,于是它开始针对X而开发。

Gettys曾讲述过有关的故事, “xterm内部如此恐怖的部分原因是它最初被计划开发成一个能驱动多个VS100显示器的单独进程。”(”part of why xterm’s internals are so horrifying is that it was originally intended that a single process be able to drive multiple VS100 displays.”)

xterm包提供基本的VT102/220终端模拟CLI和图形Tektronix 4014环境,尽管xterm是一个完整的终端模拟包,但是运行它不需要太多的资源和内存。由于这种特性,xterm包在针对老硬件设计的Linux发行版中仍然很常见。有些图形桌面环境(比如fluxbox)用它作为默认的终端模拟包。

尽管没有太多炫目的特性,但是xterm包提供了一个非常好的功能,即模拟VT220终端,最新的xterm版本甚至能模拟VT系列的颜色控制码,因而能够在脚本中使用颜色。
按住鼠标几个键同时按下CTRL可以访问xterm的几个菜单。包括xterm主菜单、VT选项菜单和VT字体选项菜单

XTerm Troubleshooting

打开xterm的时候出现下面的警告:

1
xterm: cannot load font -misc-fixed-medium-r-semicondensed--

主要因为丢失了xterm需要的字体包,解决方法如下所示:

1
$ yum install xorg-x11-fonts*

XTerm的颜色系列

XTerm是一个X Window System上的终端模拟器,用来提供多个独立的SHELL输入输出。
而使用xterm可以设置字体和背景的颜色。

1
$ xterm -fg LightGoldenrod1 -bg CornflowerBlue

具体的效果如下所示:

COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR
COLOR

NFS 配置

nfs原理:通过网络,将远程主机共享的文件系统,挂载到本机。

双方在进行nfs通讯时,必须启动portmap(F8中是rpcbind)服务。

1)在主机上启动portmap服务(F8为rpcbind,默认都为开启)

1
service rpcbind start
可以用service rpcbind status 进行检查是否开启。

2)对nfs进行配置(/etc/exports)

修改配置文件/etc/exports

添加如下代码

1
/shared/path    *(rw,sync,no_root_squash)

要共享的目录 允许使用的用户,*表示允许任意用户使用,也可以使用具体的ip,如本机可用192.168.1.168,括号中rw代表可读写,sync未知,no_root_suqash意思是以root权限访问该共享文件夹。

修改完之后,输入:

1
[root@localhost etc]# exportfs -rv

使配置文件生效。

3)在主机上启动nfs服务

1
service nfs start

4)挂载mount

1
mount -t nfs IP:/shared/path /mnt

建议:在配置完nfs后,可以本机挂载自己,试试看,是否配置正确

其间遇到的问题:

1)mount: IP:/sharedpath failed, reason given by server: Permission denied

查看配置文件exports,是否为允许挂载的客户。

2)mount: RPC: Unable to receive; errno = No route to host

首先看是否在同一网段

再者输入:

1
[root@localhost etc]# service iptables status

看防火墙是否开启,有则将其关闭

1
[root@localhost etc]# service iptables stop

3)mount: RPC: Unable to receive; errno = Connection refused

首先看nfs服务是否开启,其次看rpcbind是否开启,如果rpcbind没有运行,那在重新开启rpcbind后,要再restart nfs服务,因为重启rpcbind已对nfs的一些配置造成影响,需要restart。

Mounting NFS shares on Mac OS X

解决MacOS无法挂载NFS,Operation not permitted错误

新装的Openfiler开启nfs之后,用Macbook的图形界面通过

无法连接。

先在服务器上自己挂自己试了一下,没有问题,说明问题可能在Macbook客户端上。
在Macbook上打开终端:

1
# mount -t nfs IP:/ path localpath

#使用保留端口再试一下

1
# mount -o resvport IP:/path localpath