kk Blog —— 通用基础


date [-d @int|str] [+%s|"+%F %T"]
netstat -ltunp

搭建FTP服务器

用VSFTP搭建FTP服务器

FTP服务器是平时应用最为广泛的服务之一。VSFTP是Very Secure FTP的缩写,意指非常安全的FTP服务。VSFTP功能强大,通过结合本地系统的用户认证模块及其多功能的配置项目,可以快速有效的搭建强大的多用户FTP服务。

一、主要配置选项

VSFTP的主配置文件是/etc/vsftpd.conf 。由于可配置的选项实在太多,无法一一详谈,只能截取比较常用的功能配置选项来加以说明。完整说明可参考man vsftpd.conf。

这里需要注意的是,每个配置选项都是由“配置项目名称=配置值“所定义。在每个配置变量后,要紧跟等号,再紧跟设置的变量值。中间不允许出现空格之类的分隔符,否则导致配置错误,无法生效!

另外,如果需要开通上传功能,则应注意用来登录FTP的本地系统用户对要操作的目录需要具备写权限,否则无法上传文件!

版本vsftpd: version 2.0.6
启动VSFTPD:sudo /etc/init.d/vsftpd start
停止VSFTPD:sudo /etc/init.d/vsftpd stop
重启VSFTPD:sudo /etc/init.d/vsftpd restart

以下为常用的配置选项:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
1、listen=YES 
若设置为YES,开启监听网络。 
2、anonymous_enable 
若设置为YES,则允许匿名用户访问;若设置为NO则拒绝匿名用户访问。 
如果开启的话,则可以通过用户名ftp或者anonymous来访问,密码随便。 
3、local_enable 
若设置为YES,则允许通过本地用户帐号访问;若设置为NO,则拒绝本地用户帐号访问。如果你拒绝了陌生人访问,那么这个必须设置为YES吧,否则谁能访问你的FTP呢? 
4、write_enable 
若设置为YES,则开启FTP全局的写权限;若设置为NO,则不开。 
若为NO则所有FTP用户都无法写入,包括无法新建、修改、删除文件、目录等操作,也就是说用户都没办法上传文件!! 
5、anon_upload_enable 
若设置为YES,开启匿名用户的上传权限。前提是write_enable有开启,并且用户具有对当前目录的可写权限。 若设置为NO,则关闭匿名用户的上传权限。 
6、anon_mkdir_write_enable 
若设置为YES,开启匿名用户新建目录的权限。前提是write_enable有开启,并且用户具有对当前目录的可写权限。 若设置为NO,则关闭匿名用户新建目录的权限。 
7、dirmessage_enable 
若设置为YES,则可开启目录信息推送,也就是用户登录FTP后可以列出当前目录底下的文件、目录。 这个应该要开启吧! 
8、xferlog_enable 
若设置为YES,则开启登录、上传、下载等事件的日志功能。应开启! 
9、xferlog_file=/var/log/vsftpd.log 
指定默认的日志文件,可指定为其他文件。 
10、xferlog_std_format 
若设置为YES,则启用标准的ftpd日志格式。可以不启用。 
11、connect_from_port_20 
若设置为YES,则服务器的端口设为20。 
如果不想用端口20,可以另外通过ftp_data_port来指定端口号。 
12、chown_uploads 
若设置为YES,则匿名用户上传文件后系统将自动修改文件的所有者。 
若要开启,则chown_username=whoever也需指定具体的某个用户,用来作为匿名用户上传文件后的所有者。 
13、idle_session_timeout=600 
不活动用户的超时时间,超过这个时间则中断连接。 
14、data_connection_timeout=120 
数据连接超时时间 。 
15、ftpd_banner=Welcome to blah FTP service. 
FTP用户登入时显示的信息 。 
16、local_root=/home/ftp 
指定一个目录,用做在每个本地系统用户登录后的默认目录。 
17、anon_root=/home/ftp 
指定一个目录,用做匿名用户登录后的默认目录。 
18、chroot_local_user、 chroot_list_enable、chroot_list_file 
这个组合用于指示用户可否切换到默认目录以外的目录。 
其中,chroot_list_file默认是/etc/vsftpd.chroot_list,该文件定义一个用户列表。 
若chroot_local_user 设置为NO,chroot_list_enable设置为NO,则所有用户都是可以切换到默认目录以外的。 
若chroot_local_user 设置为YES,chroot_list_enable设置为NO,则锁定FTP登录用户只能在其默认目录活动,不允许切换到默认目录以外。 
若chroot_local_user 设置为YES,chroot_list_enable设置为YES,则chroot_list_file所指定的文件里面的用户列表都可以访问默认目录以外的目录,而列表以外的用户则被限定在各自的默认目录活动。 
若chroot_local_user设置为NO,chroot_list_enable设置为YES,则chroot_list_file所指定的文件里面的用户列表都被限定在各自的默认目录活动,而列表以外的用户则可以访问默认目录以外的目录。 
建议设置:chroot_local_user与chroot_list_enable都设置为YES。这样就只有chroot_list_file所指定的文件里面的用户列表可以访问默认目录以外的目录,而列表以外的用户则被限定在各自的默认目录活动! 
好处:所有人都被限制在特定的目录里面。如果某些特定用户需要访问其他目录的权限,只需将其用户名写入chroot_list_file文件就可以赋予其访问其他目录的权限! 
19、userlist_file、userlist_enable、userlist_deny 
这个组合用于指示用户可否访问FTP服务。 
其中,userlist_file默认是/etc/vsftpd.user_list,该文件定义一个用户列表。 
若userlist_enable设置为YES,userlist_deny设置为NO,则只有userlist_file所指定的文件里面的用户列表里面的用户可以访问FTP。 
若userlist_enable设置为YES,userlist_deny设置为YES,则userlist_file所指定的文件里面的用户列表里面的用户都被拒绝访问FTP。 
若userlist_enable设置为NO,userlist_deny设置为YES,则这个列表没有实际用处,起不到限制的作用!因为所有用户都可访问FTP。 
建议设置:userlist_enable与userlist_deny都设置为YES。这样则userlist_file所指定的文件里面的用户列表里面的用户都被拒绝访问FTP。 
好处:只需将某用户帐号加入到userlist_file所指定文件里面的用户列表,就可以起到暂时冻结该用户的功能! 
20、user_config_dir 
指定一个目录用于存放针对每个用户各自的配置文件,比如用户kkk登录后,会以该用户名建立一个对应的配置文件。 
比 如指定user_config_dir=/etc/vsftpd_user_conf,  则kkk登录后会产生一个/etc/vsftpd_user_conf/kkk的文件,这个文件保存的配置都是针对kkk这个用户的。可以修改这个文件而  不用担心影响到其他用户的配置。 

二、一种VSFTP的配置方案

首先要安装VSFTP。

源码编译或软件包安装都可以。 sudo apt-get install vsptpd 以下方案实现以下功能:
1、锁定用户在/home/ftp默认目录活动,
并保留/etc/vsftpd.chroot_list文件里面的用户列表可访问其他目录。
2、具备暂时冻结FTP用户的功能,将需暂停的用户名加入到/etc/vsftpd.usr_list即可。

设置配置文件:

复制以下文件并保存为/etc/vsftpd.conf
新建两文件:
touch /etc/vsftpd.chroot_list
touch /etc/vsftpd.user_list
新建目录:mkdir /home/ftp
新建群组:addgroup ftp
修改/home/ftp属性:chown ftp:ftp /home/ftp
新增FTP用户: adduser --shell /bin/false --home /home/ftp your_usr_name
把需要开通FTP的用户名加入到ftp群组:usermod -aG ftp your_usr_name
注意:
如果你的/etc/shells里面没有包含/bin/false,则你用上述的方法建立的用户将法访问#FTP,解决方法:编辑/etc/shells,加入/bin/false这行。

三、前面提到的问题

1、如何添加FTP用户?

设置local_enable为YES可以开放系统用户访问FTP。

在系统里面添加用户,将shell设置为/bin/false,并将其家目录若设置为/home/ftp或者其他目录。这样就可以建立只访问FTP而无法登录shell环境的用户。

注意:可以新建一个ftp组,把/home/ftp的所有者设为ftp,群组也设为ftp。然后所有新添加的FTP用户只需加入到FTP群组就可以具有对/home/ftp的访问权限了。这样也方便管理用户量比较大的FTP系统。如:

1
2
3
4
sudo addgroup ftp #如果有了就不用添加
sudo chown ftp:ftp /home/ftp #如果改过了就不用再改
sudo adduser --shell /bin/false --home /home/ftp user1 #添加用户user1
sudo usermod  -aG ftp  user1  #把用户user1加入到ftp组, 这样便可以通过用户名user1来访问FTP服务了。
2、如何临时冻结某FTP用户?

将 userlist_enable与userlist_deny都设置为YES。这样userlist_file所指定的文件里面的用户列表里面的用户都 被拒绝访问FTP。只需将某用户帐号加入到userlist_file所指定文件里面的用户列表,就可以起到暂时冻结该用户的功能!如需重新开通使用权 限,则只需从该文件中去掉相应的用户名。

3、FTP用户登入后的默认目录?是否可以改变?

可以通过local_root、anon_root来指定相应的默认目录。

4、如何锁定FTP用户可访问的目录范围?

将 chroot_local_user与chroot_list_enable都设置为YES。这样就只有chroot_list_file所指定的文件 里面的用户列表可以访问默认目录以外的目录,而列表以外的用户则被限定在各自的默认目录活动!如果某些特定用户需要访问其他目录的权限,只需将其用户名写 入chroot_list_file文件就可以赋予其访问其他目录的权限!

5、FTP用户可以有哪些访问权限?可否上传文件?

设置write_enable可以开启全局的写权限。这样FTP用户就可以在本地帐号管理系统允许的范围内进行写操作了

6、root用户无法登录ftp?

编辑/etc/ftpusers,将root注视掉就ok了

四、可能遇到的主要问题

一、

登录失败,解决方法:在/etc/shells中加入下面这句:/bin/false 就可以正常登录了

二、

上传文件时总是出现550 Permission denied错误,
查看vsftpd的配置文件sudo vim /etc/vsftpd.conf,
发现write_enable=YES这句配置项默认是被注释掉的即#write_enable=YES,
把前面的注释去掉,重启vsvfpd,一切正常了。

三、

user_config_dir 指定一个目录用于存放针对每个用户各自的配置文件。
比 如指定user_config_dir=/etc/vsftpd_user_conf, 新建/etc/vsftpd_user_conf/kkk文件,输入下面内容:

1
2
3
4
5
6
write_enable=YES
anon_world_readable_only=NO
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
local_root=/srv/ftp/ftp

这个文件保存的配置都是针对kkk这个用户的。可以修改这个文件而 不用担心影响到其他用户的配置。

四、

报下面的错误
ftp:500 Illegal PORT command. 425
ftp:Use PORT or PASV first
或者是下面的错误
ftp:500 Illegal PORT command.
ftp: bind: Address already in use
主要是由于Iptables防火墙不支持
ip_nat_ftp
ip_conntrack_ftp
在linux的ftp服务器上执行下列命令即可解决
modprobe ip_nat_ftp
modprobe ip_conntrack_ftp

五、

553 Could not create file
用 chown 或 chmod

六、

限定用户访问目录
local_root=/srv/ftp
chroot_local_user=YES
chroot_list_enable=NO

FTP命令

  • ftp 很快就会自动断开,lftp命令一样,更好用

Linux 终端连接FTP

1
2
3
4
5
6
7
$ ftp 10.85.7.97

Name (10.85.7.97:oracle): super

Password:   -- Linux 的密码是不回显的

ftp>

如果FTP 允许匿名用户,那么用户名要输入anonymous,密码任意。 不能直接敲回车。

查看FTP 命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ftp> ?
Commands may be abbreviated.  Commands are:
!               cr              mdir            proxy           send
$               delete          mget            sendport        site
account         debug           mkdir           put             size
append          dir             mls             pwd             status
ascii           disconnect      mode            quit            struct
bell            form            modtime         quote           system
binary          get             mput            recv            sunique
bye             glob            newer           reget           tenex
case            hash            nmap            rstatus         trace
ccc             help            nlist           rhelp           type
cd              idle            ntrans          rename          user
cdup            image           open            reset           umask
chmod           lcd             passive         restart         verbose
clear           ls              private         rmdir           ?
close           macdef          prompt          runique
cprotect        mdelete         protect         safe

可以通过help command 查看每个命令的说明

1
2
3
4
ftp> help put
put             send one file
ftp> help mput
mput            send multiple files

上传文件

Put命令:格式:put local-file [remote-file] 将一个文件上传到ftp
Mput命令:格式:mput local-files 将本地主机中一批文件传送至远端主机.
注意:mput命令只能将当前本地目录下的文件上传到FTP上的当前目录。比如,在/root/dave下运行的ftp命令,则只有在/root/dave下的文件linux才会上传到服务器上的当前目录下。

Put 代码示例:
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
32
ftp> pwd    -- 显示FTP上当前路径
257 "/" is current directory.
ftp> ls   -- 显示当前目录下的文件

ftp> mkdir Dave    -- 创建文件夹Dave

ftp> cd Dave      -- 进入文件夹Dave

ftp> pwd        -- 显示当前目录

ftp> lcd     -- 显示当前本地的路径,我们可以将这个路径下的这个文件上传到FTP服务器的相关位置

ftp> !      -- 退出当前的窗口,返回Linux 终端,当我们退出终端的时候,又会返回到FTP上。
$ ls  -- 显示当前目录下的文件

$ vi Dave  -- 创建文件Dave
$ vi DBA   -- 创建文件DBA
$ ls       -- 显示文件夹里的内容,等会我们将这些文件copy到FTP上

$ exit  -- 退出终端,返回FTP命令行
exit
ftp> lcd

ftp> put DBA DBA    -- 将刚才创建的文件DBA 上传到ftp的当前目录上并命名为DBA。

ftp> put DBA /Dave/SFDBA -- 将刚才创建的文件DBA 上传到ftp的当前目录上并重命名为SFDBA。

ftp> put /home/oracle/DBA /test/SFDBA  

ftp> cd test

ftp> ls
Mput 示例代码:
1
2
3
4
5
6
7
8
9
10
11
ftp>cd Dave

ftp>mput *
mput alert_log.txt?    -- 这里每个文件都要确认,按回车键就可以了

ftp> ls       -- 显示目录下的文件

ftp> delete SFDBA   --删除SFDBA 文件

ftp> mdelete a*   -- 批量删除文件
mdelete alert_log.txt?  -- 每个文件都要确认

下载文件

同样也有2个命令:get 和mget。Mget 用户批量下载。
格式:get [remote-file] [local-file]
mget [remote-files]
同样,mget 是将文件下载到本地的当前目录下。

Get 示例:
1
2
3
4
5
6
7
8
9
ftp> get /test/SFDBA /home/SFDBA

local: /home/SFDBA: Permission denied  --Linux对权限控制的很严格,下载的时候是否有对应文件夹的写权限
ftp>  get /test/SFDBA /home/oracle/SFDBA

ftp> !
$ cd /home/oracle/
$ls
Dave  DBA  dead.letter  scripts  SFDBA  sqlnet.log
Mget 示例:
1
2
3
4
5
6
7
ftp> ls

ftp> mget *
mget DBA?  -- 每个文件都要确认, 按回车即可

ftp> !
$ ls

说明的地方:FTP 当前目录下的文件下载到本地的当前目录。

断开FTP 连接

Bye命令或者quit命令:中断与服务器的连接。

1
2
ftp> bye
221 Goodbye!

js滚动标题

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
32
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>滚动标题</title>
<script language="javascript">
var title_string = "让你的标题栏文字动起来,标题也动了";
var title_length = title_string.length;
var index_count = 0;
var cmon;

function scrollTheTitle()
{
    var doc_title = title_string.substring(index_count, title_length);
    document.title = doc_title;
    index_count++;
}

function loopTheScroll()
{
    scrollTheTitle();
    if(index_count >= title_length)
    {
	index_count = 0;
	//clearTimeout(cmon);
    }
    cmon = setTimeout("loopTheScroll();",300)
}
loopTheScroll();
//-->
</script>
</head>
</html>

gcc include

本文介绍在linux中头文件的搜索路径,也就是说你通过include指定的头文件,linux下的gcc编译器它是怎么找到它的呢。在此之前,先了解一个基本概念。

头文件是一种文本文件,使用文本编辑器将代码编写好之后,以扩展名.h保存就行了。头文件中一般放一些重复使用的代码,例如函数声明、变量声明、常数定 义、宏的定义等等。当使用#include语句将头文件引用时,相当于将头文件中所有内容,复制到#include处。#include有两种写法形式, 分别是:

1
2
#include <> : 直接到系统指定的某些目录中去找某些头文件。
#include “” : 先到源文件所在文件夹去找,然后再到系统指定的某些目录中去找某些头文件。

#include文件可能会带来一个问题就是重复应用,如a.h引用的一个函数是某种实现,而b.h引用的这个函数却是另外一种实现,这样在编译的时候将会出现错误。所以,为了避免因为重复引用而导致的编译错误,头文件常具有:

1
2
3
4
#ifndef    LABEL
#define    LABEL
	//代码部分
#endif

的格式。其中LABEL为一个唯一的标号,命名规则跟变量的命名规则一样。

gcc寻找头文件的路径(按照1->2->3的顺序)

1.

在gcc编译源文件的时候,通过参数-I指定头文件的搜索路径,如果指定路径有多个路径时,则按照指定路径的顺序搜索头文件。命令形式如:“gcc -I /path/where/theheadfile/in sourcefile.c“,这里源文件的路径可以是绝对路径,也可以是相对路径。eg:
设当前路径为/root/test,include_test.c如果要包含头文件“include/include_test.h“,有两种方法:
1) include_test.c中#include “include/include_test.h”或者#include “/root/test/include/include_test.h",然后gcc include_test.c即可
2) include_test.c中#include <include_test.h>或者#include <include_test.h>,然后gcc –I include include_test.c也可

2.

通过查找gcc的环境变量C_INCLUDE_PATH/CPLUS_INCLUDE_PATH/OBJC_INCLUDE_PATH来搜索头文件位置。

3. 再找内定目录搜索,分别是
1
2
3
/usr/include
/usr/local/include
/usr/lib/gcc-lib/i386-linux/2.95.2/include

最后一行是gcc程序的库文件地址,各个用户的系统上可能不一样。
gcc在默认情况下,都会指定到/usr/include文件夹寻找头文件。

gcc还有一个参数:-nostdinc,它使编译器不再系统缺省的头文件目录里面找头文件,一般和-I联合使用,明确限定头文件的位置。在编译驱动模块时,由于非凡的需求必须强制GCC不搜索系统默认路径,也就是不搜索/usr/include要用参数-nostdinc,还要自己用-I参数来指定内核 头文件路径,这个时候必须在Makefile中指定。

4.

当#include使用相对路径的时候,gcc最终会根据上面这些路径,来最终构建出头文件的位置。如#include <sys/types.h>就是包含文件/usr/include/sys/types.h

c与汇编的关系

_start是汇编程序的入口,main是c程序的入口?
gcc 只是一个 外壳而不是真正的编译器,这真的c编译器是/usr/lib/gcc/i486-gun/4.3.2/cc1,gcc调用c编译器、汇编器和链接器完成c 代码的编译链接工作。/usr/lib/gcc/i486-linux-gun/4.3.2/collect2是链接器ld的外壳,它调用ld完成链接。

i main.c被cc1编译成汇编程序/tmp/ccRGDpua.s。
ii 这个汇编程序被as汇编成目标文件/tmp/ccidnZ1d.o
iii 这个目标文件连同另外几个目标文件(crt1.o,crti.o,crtbegin.o,crtend.o,crtn.o)一起链接成可执行文件 main。在链接过程中还用-l,选项指定一些库文件,有libc、libgcc、ligcc_s,其中有些库是共享库,需要动态链接,所以用 -dynamic-linker选项指定动态链接器是/lib/ld-linux.so.2

1
2
3
4
5
6
7
8
9
10
$ nm /usr/lib/crt1.o
00000000 R  _IO_stdin_used
00000000 D __data_start
                 U __libc_csu_fini
                 U __libc_csu_init
                 U __libc_start_main
00000000 R _fp_hw
00000000 T _start
00000000 W data_start
                 U main

U main 这一行表示main这个符号在crt1.o已经被引用了,但是还没有定义(Undefined),因此需要别的目标文件提供一个定义并且和crt1.o链接在一起。T_start表示在crt1.o中已定义为(text)。

c 程序的入口点其实是crt1.o提供的start,它先做一些初始化工作(启动例程,startup routine),然后调用我们编写的main函数。所以,main函数是程序的入口,不够准确。start才是真正的入口点,而main函数是被 _start调用的。

U __libc_start_main,这个符号在其他几个目标文件中也没有定义,所以链接生成可执行文件之后仍然是个未定义符号。事实上这个符号在 libc中定义,libc是一个共享库,它并不像其他目标文件一样链接到可执行文件main中,而是在运行时做动态链接:
i 操作系统在加载main这个程序时,首先看它有没有需要动态链接的未定义符号。
ii如果需要做动态链接,就查看这个程序指定了哪些共享库,以及用什么动态链接器来做动态链接。我们在链接时用-lc选项指定了共享库libc,用-dynamic-linker /lib/ld-linux.so.2 指定动态链接器,这些信息都会写到可执行文件中。
iii动态连接器加载共享库,在其中查找这些未定义符号的定义,完成链接过程。

c内联汇编

完整的内联汇编格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
__asm__(asembler template
		:output operands
		: input operands
		: list of clobbered registers
		);

e.g.

#include <stdio.h>
int main(void)
{
	int a=10,b;
	__asm__("movl %1,%%eax\n\t"
			"movl %%eax,%0\n\t"
			:"=r"(b)  //把%0所代表的寄存器的值输出给变量b
			:"r"(a)       //告诉编译器分配一个寄存器保存变量a的值,作为汇编程序的输入,对应%1
			:"%eax"
	);
	printf("result:%d,%d\n",a,b);
	return 0;
}