0%

Linux下碰到的一些问题

如何解决warning: no newline at end of file?

今天写了一段代码, 是在Windows下编辑的, 保存后放在linux系统下编译.

gcc和cc都产生以下的警告:

1
a.h:1:2: warning: no newline at end of file

后来发现解决这个问题产生的原因是源文件的最后一行没有回车符造成的; 解决的办法很简单, 在最后一行敲一个回车, 然后保存, 重新编译.

Linux运行文件时报错 bash $’\r’ command not found

这个主要是跨平台的问题,在Windows下编写好的sh文件,丢到Linux下运行会报错:bash: $’\r’: command not found。这是因为Windows系统的文件换行使用的是\r\n,而Unix系统是\n,可以通过下面的方式解决:

通过dos2unix来进行文件转换

1
$ dos2unix filename.sh

或者使用vim打开文件,然后使用命令:set ff=unix,保存文件即可。

send-mail: fatal: parameter inet_interfaces: no local interface found for ::1

在Linux里面使用mail发送邮件的时候报错:

1
2
$ echo 'Title' | mail -s "TEST" mail@mail.com
$ send-mail: fatal: parameter inet_interfaces: no local interface found for ::1

解决方法如下:打开文件 /etc/postfix/main.cf,将原始内容

1
2
3
inet_interfaces = localhost

inet_protocols = all

修改为:

1
2
3
inet_interfaces = all

inet_protocols = all

然后重新启动就ok了,service postfix restart

bashrc每次都不自动导入

新建的用户发现每次都不能把各种环境变量导入进来,导致类似的命令都无法使用,后面发现是少了bash_profile文件,只需要新建该文件:

1
$ touch ~/.bash_profile

然后加上如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH

保存退出重新登陆,顺利解决。

/lib64/libstdc++.so.6: version `CXXABI_1.3.8’ not found

这个问题出现在CentOS7上,编译一个软件的时候出现的,首先可以查看CXXABI可用的版本,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ strings /usr/lib64/libstdc++.so.6 | grep 'CXXABI'
CXXABI_1.3
CXXABI_1.3.1
CXXABI_1.3.2
CXXABI_1.3.3
CXXABI_1.3.4
CXXABI_1.3.5
CXXABI_1.3.6
CXXABI_1.3.7
CXXABI_1.3.8
CXXABI_1.3.9
CXXABI_1.3.10
CXXABI_1.3.11
CXXABI_1.3.12
CXXABI_TM_1
CXXABI_FLOAT128
CXXABI_1.3
CXXABI_1.3.11
CXXABI_1.3.2
CXXABI_1.3.6
CXXABI_FLOAT128
CXXABI_1.3.12
CXXABI_1.3.9
CXXABI_1.3.1
CXXABI_1.3.5
CXXABI_1.3.8
CXXABI_1.3.4
CXXABI_TM_1
CXXABI_1.3.7
CXXABI_1.3.10
CXXABI_1.3.3

查看本机的其他关于libstdc的版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ find / -name libstdc++.so.6
/var/lib/docker/overlay2/7929ef6fe4ed49351d40d41db72096133c8767d3f2aea01eab66040e38efba37/diff/usr/lib/x86_64-linux-gnu/libstdc++.so.6
/var/lib/docker/overlay2/39955c16316d10641ff5a9ed525094e7b29f0657e26332511c972b437c309598/diff/usr/lib/x86_64-linux-gnu/libstdc++.so.6
/var/lib/docker/overlay2/42fa5b2822ec5fd3837777e5b06583b6aeab9b48b2a3b168e99f9e3251084d27/diff/usr/lib/x86_64-linux-gnu/libstdc++.so.6
/var/lib/docker/overlay2/3732c1cb1021032bffa34a3858c00a3c33e4e67102eb7216412a5079ba6f4369/diff/usr/lib64/libstdc++.so.6
...
/var/lib/docker/overlay2/565aeb287ef033e4384a87fcc2f451c68db294e659124f6d772dcb1658470d8e/diff/usr/lib/x86_64-linux-gnu/libstdc++.so.6
/var/lib/docker/overlay2/hi35aa9ta0ij3t4x3k6br7gm6/diff/usr/lib/x86_64-linux-gnu/libstdc++.so.6
/var/lib/docker/overlay2/whqa9v6f82q5x1i2mxsh8fo08/diff/usr/lib/x86_64-linux-gnu/libstdc++.so.6
/var/lib/snapd/snap/core/15419/usr/lib/x86_64-linux-gnu/libstdc++.so.6
/var/lib/snapd/snap/core/15511/usr/lib/x86_64-linux-gnu/libstdc++.so.6
/usr/lib/libstdc++.so.6
/usr/lib64/libstdc++.so.6
/home/oper/anaconda3/lib/libstdc++.so.6

解决的方法,很简单,且已经奏效,把anaconda里面比较新的做一个软连接到/usr/lib64即可解决,不过记得做好备份。

安装Anjuta

1
$ sudo apt-get install anjuta

安装GUI开发包

安装图形接口和本地化等开发包。

1
$ sudo apt-get install libglademm-2.4-dev libgnomemm-2.6-dev intltool

其中,intltool是为了支持国际化/本地化,并将同时安装gettext包。

编码提示和自动补全

1
2
edit->preferences->c/c++/java/vala->autocomplete
enable smart brace completion

安装API文档

安装开发中常用的API文档,及查看器DevHelp(因libdevhelp的问题,Anjuta 的 “API帮助”插件不能工作)。

1
$ sudo apt-get install devhelp libgtkmm-2.4-doc libcairomm-1.0-doc libglib2.0-doc libgnome2-doc libsigc++-2.0-doc

解决依赖

为让Anjuta能自动配置、编译、和更好的工作,我们需要安装一些必要的工具包,比如,本地化的”intltool”;自动格式的”indent”。在“终端”执行以下命令:

1
$ sudo apt-get install autogen automake build-essential indent intltool

这样能避免出现不能新建项目、编译,以及下面这类运行时错误(其它可能还有autoconf, automake等)。

代码:

Unable to exec g++.real: No such file or directory
make: *** [main.o] 错误 2
Completed… unsuccessful

注:Ubuntu 8.04 出现的”anjuta不能build” 问题,可加装libtool(apt-get install libtool) 解决。
感谢 russell18721970 提供!(于2008-8-31)
安装完成后要重启X(即登出再重新登录),Anjuta的部分图标才能完全正常显示。怪异 =_=||

写个Hello World 的C++程序

1。打开Anjuta:点击主菜单上的“应用程序”》“编程”》“Anjuta IDE”。
2。建立项目:在Anjuta中点击菜单,“文件”》“新建”》“Project”。出现“应用程序向导”,点“前进”;工程类型选“C++”中的“Generic C++”(附图anjuta-1.png),之后点“前进”;“前进”;工程选项(Project Options)中,全选“否”,再点“前进”,应用即可。
3。查看源码:点左侧“工程”按钮,切换到“工程”选项卡。点工程名“foobar-cpp”,双击“main.cc”打开它.
4。编译运行:可以看到,main() 函数已预先写好了。我们按下“F9”编译,再按“F3”就能运行了!(这两个快捷键对应菜单在“生成”菜单下。)
安装C/C++开发文档
在编程的过程中有时会记不得某个函数的用法,通常这时查man手册是比较快的,所以把这个manpages-dev软件包安装上。想要看某个函数的用法就man它。执行安装命令:

1
$ sudo apt-get install manpages-dev

更新一下索引

1
~$ mandb -c

然后,就可以查看这些文档了。比如,fopen的:

代码:

1
~$ man fopen

find中的-print0和xargs中-0的奥妙

默认情况下, find 每输出一个文件名, 后面都会接着输出一个换行符 (‘\n’), 因此我们看到的 find 的输出都是一行一行的:

1
2
3
4
5
6
7
$ ls -l
total 0
-rw-r--r-- 1 root root 0 2010-08-02 18:09 file1.log
-rw-r--r-- 1 root root 0 2010-08-02 18:09 file2.log
$ find -name '*.log'
./file2.log
./file1.log

比如我想把所有的 .log 文件删掉, 可以这样配合 xargs 一起用:

1
2
3
4
5
$ find -name '*.log'
./file2.log
./file1.log
$ find -name '*.log' | xargs rm
$ find -name '*.log'

嗯, 不错, find+xargs 真的很强大. 然而:

1
2
3
4
5
6
7
8
9
10
11
12
$ ls -l
total 0
-rw-r--r-- 1 root root 0 2010-08-02 18:12 file 1.log
-rw-r--r-- 1 root root 0 2010-08-02 18:12 file 2.log
$ find -name '*.log'
./file 1.log
./file 2.log
$ find -name '*.log' | xargs rm
rm: cannot remove `./file': No such file or directory
rm: cannot remove `1.log': No such file or directory
rm: cannot remove `./file': No such file or directory
rm: cannot remove `2.log': No such file or directory

原因其实很简单, xargs 默认是以空白字符 (空格, TAB, 换行符) 来分割记录的, 因此文件名 ./file 1.log 被解释成了两个记录 ./file 和 1.log, 不幸的是 rm 找不到这两个文件.

为了解决此类问题, 聪明的人想出了一个办法, 让 find 在打印出一个文件名之后接着输出一个 NULL 字符 (‘\0’) 而不是换行符, 然后再告诉 xargs 也用 NULL 字符来作为记录的分隔符. 这就是 ** find 的 -print0 和 xargs 的 -0 **的来历吧.

1
2
3
4
5
6
$ ls -l
total 0
-rw-r--r-- 1 root root 0 2010-08-02 18:12 file 1.log
-rw-r--r-- 1 root root 0 2010-08-02 18:12 file 2.log
$ find -name '*.log' -print0 | xargs -0 rm
$ find -name '*.log'

你可能要问了, 为什么要选 ‘\0’ 而不是其他字符做分隔符呢? 这个也容易理解: 一般的编程语言中都用 ‘\0’ 来作为字符串的结束标志, 文件的路径名中不可能包含 ‘\0’ 字符.

阅后不即焚的source

.. note::
去年今日此门中,人面桃花相映红。
崔护《题都城南庄》

在 shell 中执行程序时,shell 会提供一组环境变量。source命令是shell的内建指定,用的最多的还是配置参数的读取和设置。

source命令的功能是用于从指定文件中读取和执行命令,通常用于被修改过的文件,使之新参数能够立即生效,而不必重启整台服务器。

较常与export等结合使用。export 可以新增,修改或删除环境变量,供后续执行的程序使用。不过export 在终端退出后就失效了。

如果需要一直有效,可以考虑写入配置文件。

类似阅后即焚的export命令

Linux export 命令用于设置或显示环境变量。比如如下所示:

1
2
3
4
$ export MYNAME='HELLOWORLD'

$ echo $MYNAME
HELLOWORLD

不过在终端退出后,这个变量定义就不复存在了。

登陆即可使用的source指令

source的用法一般如下所示:

1
$ source filename

比如最常用的:

1
$ source ~/.bash_profile

而对于第一个的设置,可以考虑将export MYNAME='HELLOWORLD'写入文件~/.bash_profile,这样每次登陆或者打开终端的时候都会自动载入了。

CentOS安装IDLE

1
2
3
yum install tkinter
yum install python-imagin
yum install python-tools

将Redhat的源更改为CentOS的源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 下载CentOS的yum安装包
wget http://ftp.nara.wide.ad.jp/pub/Linux/centos/6.4/os/x86_64/Packages/python-iniparse-0.3.1-2.1.el6.noarch.rpm
wget http://ftp.nara.wide.ad.jp/pub/Linux/centos/6.4/os/x86_64/Packages/yum-metadata-parser-1.1.2-16.el6.x86_64.rpm
wget http://ftp.nara.wide.ad.jp/pub/Linux/centos/6.4/os/x86_64/Packages/yum-3.2.29-40.el6.centos.noarch.rpm
wget http://ftp.nara.wide.ad.jp/pub/Linux/centos/6.4/os/x86_64/Packages/yum-plugin-fastestmirror-1.1.30-14.el6.noarch.rpm

# 安装yum包
rpm -ivh python-iniparse-0.3.1-2.1.el6.noarch.rpm yum-metadata-parser-1.1.2-16.el6.x86_64.rpm yum-3.2.29-40.el6.centos.noarch.rpm yum-plugin-fastestmirror-1.1.30-14.el6.noarch.rpm

# 添加163的yum源
cd /etc/yum.repos.d
wget http://mirrors.163.com/.help/CentOS6-Base-163.repo
sed -i ‘s/\$releasever/6/g’ CentOS6-Base-163.repo

# 清理yum缓存
yum clean all

# 将服务器上的软件包信息缓存到本地,以提高速度
yum makecache

内心足够强大

心情相当平静

探索未知世界的cd

.. _linux_cd_beginner:

.. note::
月桥花院,琐窗朱户,只有春知处。
宋 辛弃疾《青玉案·元夕》

cd 命令应该是除了 ls 命令外用的最多的命令了。

除非你大门不出二门不迈,做个大家闺秀。

cd 命令的含义为

cd - change directory

可以让我们访问不同的文件夹。

最简单的用法为:

1
$ cd /the/path/you/want/to/go/

接下来说一些技巧,让效率加倍。

让cd命令对参数大小写不敏感

如果你需要同时显示大写和小写的目录名(即便是你给的参数只是小写的),执行下面的bind命令,此时就可以避免Linuxlinux的尴尬。

1
$ bind "set completion-ignore-case on"

cd之进入刚才的目录

想要进入刚才进入的地方(目测没有很多人再用,但是真的很好用)运行:

1
$ cd

快速返回家目录

需要快速地回到你的家目录,输入cd即可,这里其实不用一级一级的进入

1
$ cd

进入某用户的家目录

这个需要你有root权限

1
cd ~username

进入username的家目录。

这些是一些比较基础和入门的,还有一些高级一点的,这些技巧可能用的比较少,不过也是很有帮助的。

一步直达 - CDPATH的妙用

适用于贼长的目录路径

如果你的目录路径足够长长长长长长长长长长长长长长长
那么一定要用一下这个技巧。

变量CDPATH定义了目录的搜索路径,这个设置特别适合经常需要进入到某个目录,此时这个设置就及其有用

1
$ export CDPATH=/the/first/path/you/want/to/go/:/the/second/path/you/want/to/go

现在,不用输入/the/first/path/you/want/to/go/hello 这样长了,我可以直接输入下面的命令进入 :

1
$ cd hello

此时即可一步直达/the/first/path/you/want/to/go/hello目录

快速折返的 cd和alias

​ 有没有碰到这个痛点,一直需要cd ..,如此这番,好多次,那么此时就可以通过结合cd和alias的强大结合,快速折返,如下:在一个多级的目录下希望返回上级目录是,经常要使用cd ../../../../../..,如果层次很多,比如,在目录/home/username/1/2/3/4/5/6/7/8/9中,希望返回,那么可以使用cd ../../../,或者在bashrc中定义如下:

1
2
3
4
5
6
7
8
9
10
alias ..=”cd .. ”
alias ..2=”cd ../..”
alias ..3=”cd ../../..”
alias ..4=”cd ../../../..”
alias ..5=”cd ../../../../.. ”
alias ..6=”cd ../../../../../.. ”
alias ..7=”cd ../../../../../../.. ”
alias ..8=”cd ../../../../../../../.. ”
alias ..9=”cd ../../../../../../../../.. ”
alias ..10=”cd ../../../../../../../../.. ”

这样就可以通过..N来快速返回N级父目录了。

进入某用户的家目录

如果你拥有root权限,可以进入某个用户的家目录

1
$ cd ~username

其中username为实际用户名

创建后立即进入该目录的mkdircd

经常需要的操作是创建一个目录,然后再进入该目录,那么可以把下面的一行语句放在bashrc里面即可实现。

1
function mkdircd () { mkdir –p "$@" && eval cd "\"\$$#\""; }

此时使用如下的命令进行测试:

1
$ mkdircd /tmp/the/test/folder/we/want/to/create

!$

这个命令目测,用的人不多,其实比较有用,且有效。

1
$ cd !$

表明的意思是将上一个命令的参数作为cd的参数来使用。

用shopt –s cdspell自动纠正cd命令的目录名输入错误

使用shopt -s cdspell可以自动修正cd时拼写错误的目录名。

如果你在输入时经常犯些错误,这个命令是很有用的。详见以下示例:

1
2
3
4
5
6
7
8
9
10
11
# cd /etc/mall

-bash: cd: /etc/mall: No such file or directory

# shopt -s cdspell

# cd /etc/mall

# pwd

/etc/mail

注: 当我错误的把mail敲成了mall,用这个命令mall就自动被换成了mail

详细的配置信息可以参考:

.. literalinclude:: ../../src/linux-bashrc.sh

cd

cd 命令应该是除了 ls 命令外用的最多的命令了。除非你大门不出二门不迈,做个大家闺秀。

cd 命令的含义为

change directory

可以让我们访问不同的文件夹。

最简单的用法为:

1
$ cd /the/path/you/want/to/go/

接下来说一些技巧,让效率加倍。

让cd命令对参数大小写不敏感

如果你需要同时显示大写和小写的目录名(即便是你给的参数只是小写的),执行下面的bind命令,此时就可以避免Linuxlinux的尴尬。

1
$ bindset completion-ignore-case on”

进入刚才的目录

想要进入刚才进入的地方(目测没有很多人再用,但是真的很好用)运行:

1
$ cd

快速返回家目录

需要快速地回到你的家目录,输入cd即可,这里其实不用一级一级的进入

1
$ cd

进入某用户的家目录

这个需要你有root权限

1
cd ~username

进入username的家目录。

这些是一些比较基础和入门的,还有一些高级一点的,这些技巧可能用的比较少,不过也是很有帮助的。

结合CDPATH的妙用

变量CDPATH定义了目录的搜索路径:

1
$ export CDPATH=/the/path/you/add/:/another/path/

现在,不用输入cd /the/path/you/add/hello/ 这样长了,我可以直接输入下面的命令进入 /the/path/you/add/hello/

1
$ cd html

!$

这个命令目测,用的人不多,其实比较有用,且有效。

1
$ cd !$

表明的意思是将上一个命令的参数作为cd的参数来使用。

用shopt –s cdspell自动纠正cd命令的目录名输入错误

使用shopt -s cdspell可以自动修正cd时拼写错误的目录名。

如果你在输入时经常犯些错误,这个命令是很有用的。详见以下示例:

1
2
3
4
5
6
7
8
9
10
11
# cd /etc/mall

-bash: cd: /etc/mall: No such file or directory

# shopt -s cdspell

# cd /etc/mall

# pwd

/etc/mail

注: 当我错误的把mail敲成了mall,用这个命令mall就自动被换成了mail

私信某个用户的write命令

.. _linux_write_beginner:

.. note::
言者无罪,闻者足戒。
《诗经》小序

Linux write命令会将信息传给某一个 mesg 设定为 yes 的上线使用者(可以输入mesg,如果返回is yes就可以收到)。当使用终端登陆的时候,可以使用EOF (通常用 Ctrl+D)。所有人均可以使用该命令。

官方的定义为:

write - send a message to another user

命令格式

1
$ write user [ttyname]

相比于wall命令,多了一个[ttyname]这个参数。

在使用write的时候,用户会收到如下的信息格式:

Message from yourname@yourhost on yourtty at hh:mm …

而多了的[ttyname]这个参数用于在一个用户登陆了很多的终端后,可以指定向哪个终端发送命令。

这个命令的使用场景为单独向某个用户发送命令,比如账户快到期了、用户要续费了等等。

如下:

1
2
3
4
5
6
7
$ write user
Dear user,
We want to make you aware that your account will disable in two weeks.
Please save all your works or contact me for longer use.
Regards,
Admin
Ctrl+D #退出

所有登陆的终端都会收到这个消息:

1
2
3
4
5
6
7
8
Message from admin@localhost on pts/4 at 22:39 ...
Dear user,
We want to make you aware that your account will disable in two weeks.
Please save all your works or contact me for longer use.
Regards,
Admin
EOF

如果用户没有登陆,会有下面的输出:

1
2
$ write user
write: user is not logged in

而如果一个用户登陆了好几个终端,在不指定的情况下会有如下提示:

1
2
$ write user
write: useris logged in more than once; writing to pts/N