欢迎光临
我们一直在努力

OPENWRT编译

shenzt@sina.com阅读(537)

来坛子一年多了,一直潜水,改硬件什么的水平不行,openwrt也不怎么会编,写点教程希望能抛砖引玉
我实在UBUNTU环境下编译的,怎么安装就省略了,直接开始吧。
首先是
sudo apt-get install gcc g++ binutils patch bzip2 flex bison make autoconf gettext texinfo unzip sharutils subversion libncurses5-dev ncurses-term zlib1g-dev

可能make menuconfig的时候提示缺少AWK的,可以这样sudo apt-get install gawk

然后是下载源码

TRUNK版的是
svn checkout svn://svn.openwrt.org/openwrt/trunk
cd trunk
./scripts/feeds update -a
./scripts/feeds install -a

DREAMBOX版的是
svn co svn://svn.openwrt.org.cn/dreambox/backfire openwrt-dreambox
cd openwrt-dreambox
./scripts/feeds update -a
./scripts/feeds install -a

然后就是make menuconfig
我以841n v3做例子,编个带USB脱机下载的固件







其实选哪个我也不怎么清楚,大家可以参考别人编译的openwrt里面有哪些软件包、

841的USB是改出来的所以直接编译是没有USB的
下面添加USB支持
打开trunk/target/linux/ar71xx/files/arch/mips/ath79
貌似841n v3用的是mach-tl-wr941nd.c而不是mach-tl-wr841nd.c保险起见我两个都换

旁边那1043的是带USB的,借鉴一下?

发现缺什么了不?顺便看看1041n


下面是改8M,
/trunk/target/linux/ar71xx/image/makefile

还有trunk/tools/firmware-utils/src/mktplinkfw.c


最后是把蛋疼的无线开启,atheros的网卡需要改package/mac80211/files/lib/wifi/mac80211.sh和package/madwifi/files/lib/wifi/madwifi.sh,拉到最下有个蛋疼的

把1改为0就OK
本人会的仅限于此了,希望大家批评和指出

openwrt基本编译

shenzt@sina.com阅读(446)

openwrt基本编译

本文由明月永在原创,复制或者引用请注明出处www.myopenwrt.org

编译首先得搭建编译环境,一般推荐用Ubuntu系统,对新手较易上手,使用的人多,碰到问题也容易解决。

特别提醒 一下,编译是一个相当复杂的过程,尤其是新手可能会碰到N多的错误提示,所以提示全是英文的,如果英语水平,根本 看不懂提示内容,你还是不要玩编译的好,要玩几乎是在自虐。还有编译得用linux系统,要求有一定的linux基础,如果你连终端在哪里,隐藏文件怎么看,简单的一些命令都不懂,也不要玩了哈。

Ubuntu系统的安装可在自行搜索,也不难,主要注意下分区时,如果原来硬盘有文件,不要选择全部来安装,否则会数据丢失。

本人使用的是Ubuntu12.04 64位系统,当然也可以用新系统。要编译首先得弄好编译环境,也就是安装一些编译所必须用到的软件。编译openwrt一般是交叉编译,交叉编译就是指编译非x86的软件,和编译所用到的系统的架构不一样的。所编译出来的软件也不能直接在编译的系统里运行。

打开终端,输入以下命令sudo apt-get install gcc g++ binutils patch bzip2 flex bison make autoconf gettext texinfo unzip sharutils subversion libncurses5-dev ncurses-term zlib1g-dev  gawk

这里需要提示一下,上面这个命令是针对Ubuntu12.04系统的,新的系统有些软件的版本可能不一样,比如旧的是1.0版本,Ubuntu14.10可能是1.5版本,所以不能完全生搬硬套。要灵活运用。还有些openwrt版本,比如开发版本,在编译时可能会提示少其它的软件,根据提示安装所缺少的软件即可,一般来说如果少一个aaa软件,安装时,最好把aaa.dev也同时装上。新安装的Ubuntu系统最好设置好并更新升级了所有软件后,才安装以上软件,要不可能会提示软件没有。

装好编译环境后,就到
https://dev.openwrt.org/wiki/GetSource
openwrt官网查找自己所需要的版本来编译。获取源码的方式 有两种,一种是用git,一种是svn,这两种方式 都得安装软件,如果没有就得搜索一下再安装好。本人一般都用svn来获取源码 。编译openwrt的过程里会生成很多的临时文件,体积非常大,虽然固件才几M,编译过程 所生成的文件一般是10G级的,如果你编译多个平台和多个型号,就需要更多的空间。加安装系统最少需要10G,至少 得预留40G+以上的空间。不然编译到一半时,提示没有空间,是非常郁闷的事。

以下的svn获取源码的命令:
attitude_adjustment就是所说的AA,上一个稳定版本,当前的稳定版本是barrier_breaker,trunk版本是大家所说的CC,建议用BB来编译。

SVN

You can checkout the source from the OpenWrt Subversion repository using one of the following commands:

  • Development branch: ChangeLog
    svn co svn://svn.openwrt.org/openwrt/trunk/
    
  • Barrier Breaker 14.07 branch: ChangeLog
    svn co svn://svn.openwrt.org/openwrt/branches/barrier_breaker
    
  • Attitude Adjustment 12.09 branch: ChangeLog
    svn co svn://svn.openwrt.org/openwrt/branches/attitude_adjustment
    
  • Backfire 10.03 branch: ChangeLog
    svn co svn://svn.openwrt.org/openwrt/branches/backfire
    
  • Kamikaze 8.09 branch: ChangeLog
    svn co svn://svn.openwrt.org/openwrt/branches/8.09
    
  • Kamikaze 7.09 branch: ChangeLog
    svn co svn://svn.openwrt.org/openwrt/tags/kamikaze_7.09
    

如果用BB源码 ,则在终端输入

svn co svn://svn.openwrt.org/openwrt/branches/barrier_breaker
之后会,自动下载源码。
源码下载完后
cd barrier_breaker
安装 luci,openwrt源码默认是不带luci的,得用命令来安装
./scripts/feeds update -a 
./scripts/feeds install -a 

完成之后,就可以在终端执行make menuconfg来选择自己所需要的软件
软件选择可以参考一下恩山的教程
http://www.right.com.cn/forum/thread-83746-1-1.html
当年我也是从这里起步的。
第一次编译不要选太多东西,选择好型号后,必选luci界面下的一些软件,要不登录会
没界面。其它软件可以尽量少选,先尝试下是否能编译出固件。能成功生成固件,说明编译环境没有问题。

配置好后退出 保存,建议用以下命令来编译

make -j5 V=99 2>&1 |tee build.log |grep -i error

这个命令可以生成日志,日志名为buil.log,保存在最高目录下。以方便出错查找原因。-j5参数是4核cpu使用的,其它cpu可以使用内核数量N+1来相应 修改。

输入这个命令后,经过漫长的等待就会出来固件,如果中途有错,查找日志解决后,再执行以上命令就行,一般不必要重新再来。

在编译的过程中,会自动下载应用软件的源码到dl目录下面,选择的软件越多,所需要下载的数据会越大,这些软件的源码 基本都在国外的,所以下载速度极其的慢,甚至有些软件被墙了的,根本下载不了。首次编译一般会耗时几小时,视网络下载速度而定。如果下载不了打看编译日志,来找到错误所在的地方,可以搜索***来定位,有错误的地方一般以这个为标示。然后再找到软件的下载网址,会在出错报告的前面,有ftp或者http链接,里面包含有相应软件名的网址,然后手动下载之后放到dl目录即可。

像我用四核的cpu,全部编译一个16M固件得花一个多小时,不包括下载的时间。由于很多源码在墙外,所以强烈建议大家在弄好翻wall之后,再编译。

新手应该还要注意,openwrt官方所设定的固件大小是按路由出厂的闪存来定的,起步为4M,小于4M的官方都不会支持。所以有一些型号,基本加不了软件,加了软件就会不出固件,因为超出了最大的体积。碰到这种情况,可以少选一些软件。如果已经硬 改过的,需要修改相应的文件来改变默认固件的大小。

还有新手在配置软件时,千万要注意一点,选择软件时会自动选上所依赖的文件,保存之后,下次再去除这个软件,所选的依赖文件并不会自动取消。这样会残留一些没有用的软件在固件里,对于空间非常小的闪存来说,这是很不应该的。所以配置一定要小心,弄好的配置做个备份。

Debian/Ubuntu系统中安装和配置UFW-简单的防火墙

shenzt@sina.com阅读(503)

自从计算机互连后,各种服务迅速发展。用户使用的电子邮件、社交媒体、在线商城、即时聊天甚至网络会议等服务如雨后春笋般涌现。但从另一方面来说,这些连接服务也具有双刃剑,比如它们当中的病毒、恶意软件、特洛伊木马等会向计算机发送恶意消息。

作为最大的计算机网络,互联网上可并不都是善意的用户。因此,为了确保我们的计算机或服务器安全,我们需要进行保护。
在你的计算机或服务器上一个必须有的组件就是防火墙。在维基百科中,其定义是:
防火墙是计算机中一款应用软件或基于硬件的网络安全系统。它根据应用配置的规则,分析数据包,然后决定是否允许此数据包通过,来控制整个系统的网络数据进出访问权限。
iptables 是一款广泛使用于服务器的防火墙。它是一款应用程序,它会根据一系列规则来管理服务器上的进出数据流。一般来说,只有可信任的连接才允许进入服务器。但 iptables 是在控制台模式下运行,它非常的复杂。不熟悉 iptables 配置规则和命令的用户可以读读下面的文章,它描述了如何使用iptables防火墙。

推荐阅读:

iptables—包过滤(网络层)防火墙 http://www.linuxidc.com/Linux/2013-08/88423.htm

Linux防火墙iptables详细教程 http://www.linuxidc.com/Linux/2013-07/87045.htm

iptables+L7+Squid实现完善的软件防火墙 http://www.linuxidc.com/Linux/2013-05/84802.htm

iptables的备份、恢复及防火墙脚本的基本使用 http://www.linuxidc.com/Linux/2013-08/88535.htm

Linux下防火墙iptables用法规则详解 http://www.linuxidc.com/Linux/2012-08/67952.htm

Debian/Ubuntu 系统中安装 UFW 防火墙

为了降低 iptables 设置的复杂度,有许多对应的前端应用。如果你运行的是 Ubuntu linux 系统的话, UFW 就是一款默认的防火墙工具。我们开始来探讨 UFW 防火墙吧。

什么是 UFW

UFW (简单的防火墙) 是广泛使用的 iptables 防火墙的前端应用,这是非常适合于基于主机的防火墙。UFW 即提供了一套管理网络过滤器的框架,又提供了控制防火墙的命令行界面接口。它给那些不熟悉防火墙概念的 Linux 新用户提供了友好、易使用的用户界面。

同时,另一方面,它也提供了命令行界面,为系统管理员准备了一套复杂的命令,用来设置复杂的防火墙规则。UFW 对像 Debian、Ubuntu 和 Linux Mint 这些发布版本来说也是上上之选。

UFW 基本用法

首先,用如下命令来检查下系统上是否已经安装了 UFW 。
$ sudo dpkg –get-selections | grep ufw
如还没有安装,可以使用 apt 命令来安装,如下所示:$ sudo apt-get install ufw

在使用前,你应该检查下 UFW 是否已经在运行。用下面的命令来检查。
$ sudo ufw status
如果你发现状态是: inactive , 意思是没有被激活或不起作用。

启用/禁用 UFW

要启用它,你只需在终端下键入如下命令:
$ sudo ufw enable
在系统启动时启用和激活防火墙

要禁用,只需输入:
$ sudo ufw disable

列出当前UFW规则

在防火墙被激活后,你可以向里面添加你自己的规则。如果你想看看默认的规则,可以输入。
$ sudo ufw status verbose
输出样例:
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing)
New profiles: skip
$

添加UFW规则

如你所见,默认是不允许所有外部访问连接的。如果你想远程连接你的机器,就得开放相应的端口。例如,你想用 ssh 来连接,下面是添加的命令。

允许访问
$ sudo ufw allow ssh
[sudo] password for pungki :
Rule added
Rule added (v6)
$
再一次检查状态,会看到如下的一些输出。

$ sudo ufw status

To      Action          From
—      ———–         ——
22      ALLOW           Anywhere
22      ALLOW           Anywhere (v6)

如果你有很多条规则,想快速的在每条规则上加个序号数字的话,请使用 numbered 参数。

$ sudo ufw status numbered

To      Action          From
——      ———–         ——
[1] 22      ALLOW           Anywhere
[2] 22      ALLOW           Anywhere (v6)

第一条规则的意思是所有通过22端口访问机器的 tcp 或 udp 数据包都是允许的。如果你希望仅允许 tcp 数据包访问应该怎么办?可以在服务端口后加个 tcp 参数。下面的示例及相应的输出。

$ sudo ufw allow ssh/tcp

To      Action          From
——      ———–         ——
22/tcp      ALLOW           Anywhere
22/tcp      ALLOW           Anywhere (v6)

拒绝访问

添加拒绝规则也是同样的招数。我们假设你想拒绝 ftp 访问, 你只需输入

$ sudo ufw deny ftp

To      Action          From
——      ———–         ——
21/tcp      DENY            Anywhere
21/tcp      DENY            Anywhere (v6)

添加特定端口

有时候,我们会自定义一个端口而不是使用标准提供的。让我们试着把机器上 ssh 的 22 端口换成 2290 端口,然后允许从 2290 端口访问,我们像这样添加:

$ sudo ufw allow 2290/ssh (译者注:些处演示例子有问题)

To      Action          From
—      ———–         ——
2290        ALLOW           Anywhere
2290        ALLOW           Anywhere (v6)

你也可以把端口范围添加进规则。如果我们想打开从 2290到2300 的端口以供 tcp 协议使用,命令如下示:

$ sudo ufw allow 2290:2300/tcp

To          Action          From
——          ———–         ——
2290:2300/tcp       ALLOW           Anywhere
2290:2300/tcp       ALLOW           Anywhere (v6)

同样你想使用 udp 的话,如下操作。

$ sudo ufw allow 2290:2300/udp

To          Action          From
——          ———–         ——
2290:2300/udp       ALLOW           Anywhere
2290:2300/udp       ALLOW           Anywhere (v6)

请注意你得明确的指定是 ‘tcp’ 或 ‘udp’,否则会出现跟下面类似的错误信息。

ERROR: Must specify ‘tcp’ or ‘udp’ with multiple ports

添加特定 IP

前面我们添加的规则都是基于 服务程序 或 端口 的,UFW 也可以添加基于 IP 地址的规则。下面是命令样例。

$ sudo ufw allow from 192.168.0.104

你也可以使用子网掩码来扩宽范围。

$ sudo ufw allow form 192.168.0.0/24

To      Action          From
—      ———–         ——
Anywhere    ALLOW           192.168.0.104
Anywhere    ALLOW           192.168.0.0/24

如你所见, from 参数仅仅限制连接的来源,而目的(用 To 列表示)是所有地方。让我们看看允许访问 22端口(ssh)的例子。
$ sudo ufw allow to any port 22
上面的命令会允许从任何地方以及任何协议都可以访问22端口。

组合参数

对于更具体的规则,你也可以把 IP 地址、协议和端口这些组合在一起用。我们想创建一条规则,限制仅仅来自于 192.168.0.104 的 IP ,而且只能使用 tcp 协议和通过 22端口 来访问本地资源。我们可以用如下所示的命令。
$ sudo ufw allow from 192.168.0.104 proto tcp to any port 22
创建拒绝规则的命令和允许的规则类似,仅需要把 allow 参数换成 deny 参数就可以。

删除规则

某些时候需要删除现有的规则。再一次使用 UFW 删除规则是很简单的。在上面的示例中,已经创建了如下的规则,现在你想删除它们。

To      Action          From
—      ———–         ——
22/tcp      ALLOW           192.168.0.104
21/tcp      ALLOW           Anywhere
21/tcp      ALLOW           Anywhere (v6)

删除规则有两个方法。

方法1

下面的命令将会 删除 与 ftp 相关的规则。所以像 21/tcp 这条 ftp 默认访问端口的规则将会被删除掉。
$ sudo ufw delete allow ftp

方法2

但当你使用如下命令来删除上面例子中的规则时,
$ sudo ufw delete allow ssh

或者

$ sudo ufw delete allow 22/tcp

会出现如下所示的一些错误
Could not delete non-existent rule
Could not delete non-existent rule (v6)

我们还有一招。上面已经提到过,可以序列数字来代替你想删除的规则。让我们试试。

$ sudo ufw status numbered

To      Action          From
—      ———–         ——
[1] 22/tcp      ALLOW           192.168.0.104
[2] 21/tcp      ALLOW           Anywhere
[3] 21/tcp      ALLOW           Anywhere (v6)

然后我们删除正在使用的第一条规则。按 “ y ” 就会永久的删除这条规则。

$ sudo ufw delete 1

Deleting :
Allow from 192.168.0.104 to any port 22 proto tcp
Proceed with operation (y|n)? y

从这些用法中你就可以发现它们的不同。

方法2 在删除前需要 用户确认 ,而 方法1 不需要。
重置所有规则
某些情况下,你也许需要 删除/重置 所有的规则。可以输入。

$ sudo ufw reset

Resetting all rules to installed defaults. Proceed with operation (y|n)? y

如果你输入“ y ”, UFW 在重置你的 ufw 前会备份所有已经存在规则,然后重置。重置操作也会使你的防火墙处于不可用状态,如果你想使用得再一次启用它。

高级功能

正如我上面所说,UFW防火墙能够做到iptables可以做到的一切。这是通过一些规则文件来完成的,他们只不过是 iptables-restore 所对应的文本文件而已。是否可以通过 ufw 命令微调 UFW 的与/或逻辑来增加 iptables 命令其实就是编辑几个文本文件的事。
/etc/default/ufw: 默认策略的主配置文件,支持 IPv6 和 内核模块。
/etc/ufw/before[6].rules: 通过 ufw 命令添加进规则之前里面存在的规则会首先计算。
/etc/ufw/after[6].rules: 通过 ufw 命令添加进规则之后里面存在的规则会进行计算。
/etc/ufw/sysctl.conf: 内核网络可调参数。
/etc/ufw/ufw.conf: 设置系统启动时 UFW 是否可用,和设置日志级别。

结论

UFW 作为 iptables 的前端应用,给用户提供了简单的接口界面。使用着不需要去记非常复杂的 iptables 语法。UFW 也使用了‘ 简单英语 ’作为它的参数。

像 Allow、deny、reset 就是他们当中的一部分。我相信有很多很多 iptables 前端应用,但 UFW 绝对是那些想要快速、简单的就建立自己的防火墙,而且还很安全的用户的最佳替代品之一。请输入 man ufw 查看 ufw 用户手册,来了解更多详情。

魔改版BBR一键安装脚本 For Debian8 / Ubuntu16 +

shenzt@sina.com阅读(466)

简介

BBR相信大家都不陌生,是谷歌开发的一个存在于Linux内核中的拥塞算法。为了优化国内与服务器之间的网络质量,loc的大佬专门魔改改进了下这个BBR,成为了新的BBR魔改版。我也就乘机水一篇文章好了~在Debian 8 和Ubuntu16 + 系统上一键部署魔改版BBR,自动换内核成 4.10.15 ,自动安装Headers。用户只需要将系统安装成 Debian 8 或者 Ubuntu 16 即可,剩下的交给脚本来吧。
Github地址:https://github.com/FunctionClub/YankeeBBR
bbr1.png

参考资料

魔改BBR原帖:http://www.hostloc.com/thread-372277-1-2.html
萌新教程: http://www.hostloc.com/thread-372335-1-1.html
脚本技术: https://doub.io/wlzy-16/

部分商家的VPS可能会遇到换内核之后无法启动系统的情况,所以请运行脚本前一定要备份好重要数据!!

安装使用

Bash
wget -N --no-check-certificate https://raw.githubusercontent.com/FunctionClub/YankeeBBR/master/bbr.sh && bash bbr.sh install

安装过程中如果出现这张图片,请选择NO 来删除其他内核:

bbr2.png

然后根据提示重启系统。
重启完成后,运行

Bash
bash bbr.sh start

即可启动魔改版BBR。

查看魔改BBR状态

Bash
sysctl net.ipv4.tcp_available_congestion_control

如果看到有 tsunami 就表示开启成功!

bbr3.png

简单 PHP + MySQL 数据库动态网站制作

shenzt@sina.com阅读(369)

简单 PHP + MySQL 数据库动态网站制作

在这篇文章中,我尽量用最浅显易懂的语言来说明使用 PHP, MySQL 制作一个动态网站的基本技术。阅读本文需要简单的 HTML 基础知识和(任一编程语言的)编程基础知识(例如变量、值、循环、语句块的概念等)。

PHP 基础

概述

PHP 是一种解释性语言,可用于对网页进行预处理。PHP 脚本在服务器端运行,其运行结果是一个可用来显示的网页。尽管可以完成许多类似工作,但是 JavaScript 和 PHP 的一大区别就是,JavaScript 是在浏览器端运行的。事实上,浏览器会接收 JavaScript 代码并运行它,所以用户是可以查看 JavaScript 代码的。而 PHP 不会将原始代码交给浏览器, 只会将其运行的结果交给浏览器,所以用 PHP 处理用户登陆、用户权限等问题是安全可靠的。

PHP 与 HTML

实际编写的时候,通常采用的方式是建立扩展名为 php 的文件(网页文件本质上是文本文件)。编写 php 代码和编写 html 代码并没有多少区别,而最方便的地方在于,在一个 php 文件中,两种代码是可以混编的。

规则:php 代码需要包含在 <?php ... ?> 标签中,就像这样:

<?php

    // code goes here

?>

提示:这是一个 php 和 html 混编的较为生动的例子。

<?php

    if ($var == true):

?>

<html id="ie6">

<?php

    else:

?>

<html id="ie8">

<?php

    endif;

?>

这里的意思是,如果 php 中的变量 $var 的值为 true,则放置一个标签,否则放置另一个标签。PHP 的 if 语句可以像上面那样写,也可以写成C/C++风格的:

<?php

    if ($var == true) {
        // do something
    } else {
        // do other things
    }

?>

关于 PHP 中的操作符

PHP 采用的操作符和 C/C++ 是类似的,例如用 = 表示赋值,== 表示相等性比较,以及 <> (小于、大于)比较符、! 取反、&&逻辑与、||逻辑或等。当然,也支持 +-*/ 等数学表达式的运算。

关于 PHP 中的变量

PHP 中变量的命名一律以符号 $ 开头,可以使用下划线,例如 $is_logged_in 就是一个表意清晰的变量名。和大多数编程语言不同,PHP 中变量没有类型的概念,而且不用声明就可以直接使用。虽然很爽,但是变量多了的时候也容易混乱,这一点需要特别注意。

关于 PHP 中的语句

这一点 PHP 和许多其他常见的编程语言很类似,也可以用 if...else 选择语句(之前已经见过了),PHP 还包括 while 循环、foreach 循环等,以后遇到了会详细介绍。

MySQL 基础

使用 MySQL 数据库是存储数据的一种方法,MySQL 需要和 PHP 配合来完成对数据库的查询(这里术语“查询”包括写入、更新、读取等)操作。利用 MySQL,你可以创建许多数据库(database),每个数据库可以包含多个表(table),而每个表包含若干字段。为了高效,一般会采取分类维护多个表的方式,而不是把所有数据都储存在同一个表中。

MySQL 需要服务器支持。使用的第一步是建立一个数据库,可以用相应的图形化工具(例如 phpMyAdmin)来建立数据库,也可以在终端直接使用下列 SQL 语句来创建一个名为 database_name 的数据库:

CREATE DATABASE database_name;

创建好数据库之后,需要创建表。可以通过下列 SQL 语句来创建一个名为 table_name 的表:

USE database_name;

CREATE TABLE table_name (
  first_name varchar(30),
  last_name varchar(30),
);

第一句说明在哪个数据库中添加表,第二个说明添加的表的详情。这里我们在表中添加了两个字段,分别叫做 first_namelast_name,它们的类型是 varchar(30)。其中 varchar 是一种可变长字符类型,而 30 代表了最大长度。

其他常见的数据类型如下:

VARCHAR(100) --可变字符 
CHARACTER(1) --定长
INTEGER --整数
DECIMAL(10, 2) --小数(小数点前后的位数)
TIMESTAMP --日期和时间
DATE --日期

你可能已经看出来了,MySQL 的注释符为 --。你可能觉得没太大用,但是它却是一种稍后要提到的攻击的关键之处。此外,一般字符串都应该使用变长的VARCHAR类型,而非定长的CHARACTER类型,因为后者会占据更多的空间,而这是不必要的。

使 PHP 和 MySQL 协作

第一种方式

现在你已经创建好了 SQL 数据表,并对 PHP 语言有了一个概览。下面我们直奔主题,学习如何对数据表进行查询。

为了使 PHP 和 MySQL 进行交互,需要为 PHP 提供你的数据库用户名、密码、数据库名和数据表名。当然,最重要的,查询操作的 SQL 语句。我们一一来观察是如何实现的。

<?php

    define('DB_HOST', 'localhost');
    define('DB_USER', 'renfei');
    define('DB_PASS', 'root');
    define('DB_NAME', 'database_name');

    $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
    $query = "INSERT INTO table_name (column1, column2) VALUES ('value1', 'value2')";

    mysqli_query($dbc, $query);

?>

下面来解释一下这一坨代码的工作原理。

  • 首先 3~6 行为 PHP 中的 define 语句,作用很明显,把 DB_HOST 定义为 localhost,下面的代码中就可以使用 DB_HOST 来代替 localhost。这样做的好处在于,如果mysqli_connect函数在代码中出现多次,修改参数的时候则只需修改 define语句,非常方便。
  • 然后是一个叫做 mysqli_connect() 的函数,它需要四个变量,分别是主机名、用户名、密码、数据库名。这个函数执行后的返回值传递给变量 $dbc$dbc 包含了一次数据库连接。注意,这个变量名是任意的,并不强制要求叫做$dbc
  • 然后,我们把要对数据库执行的操作对应的 SQL 语句以字符串的形式赋给变量 $query。这个变量名也是任意的。应该注意到,这里的 SQL 语句是不以分号结尾的。
  • 最后,我们执行 mysqli_query(); 函数,该函数有两个参数,分别是一个数据库连接,和一个 SQL 查询操作。执行该函数后,相应的查询操作被执行。

如果把这些代码保存成一个网页,当用户打开网页的时候,如果各项参数正确,它就会完整地运行下去。

这里的 SQL 语句的含义是向叫做 table_name 的表中插入一行,其中把 colume# 字段的值相应地设置为 value#。这里只设定了两个字段的数值(表中还可以有其他字段;没有显式说明的字段则留空或者使用数据表指定的默认值)。该语句的通用形式为:

INSERT INTO table_name (column1, column2, ...) VALUES ('value1', 'value2', ...)

如果你要做的仅仅是执行一个 SQL 语句,那么使用这种模式就可以完成。提醒一下,$dbc 变量往往是重复使用的。

另一个常用的 SQL 语句就是修改某一行。它的形式为:

UPDATE table_name SET
column1 = 'preferred_value1',
column2 = 'preferred_value2',
...,
WHERE id = '$id'

当然,这个语句应该是写到一行的,不过为了清晰我分开来写。它的含义是,修改名为 table_name 的表中字段 id 的值是变量 $id 的值的所有行,把 column1 字段的值设为 preferred_value1,把 column2 字段的值设为 preferred_value2,依此类推。这里我们还看到,值既可以用常量表示,也可以用变量表示。

注意:会修改所有符合 WHERE 子句限定的条件的行(如果省略 WHERE 子句,就会修改所有行)。WHERE 子句可以设定多个条件,也可以使用比较运算符。例如:

WHERE age > 20 AND gender = 'male'
WHERE is_admin = 'true' OR id = '$id'

(如果你想问 ANDOR 为什么不是符号 &&|| 的话,我想提示你,不要把 PHP 语言和 SQL 语言搞混了。这是 SQL 语言,而我只说过 PHP 语言和 C/C++ 有些类似)。

下面介绍其他 SQL 语句。

-删除table_name表中的所有行
DELETE FROM table_name

--删除table_name表中email字段为david@example.com的所有行
DELETE FROM table_name WHERE email = 'david@example.com'

--删除table_name
DROP TABLE table_name

--删除table_name表中的score字段
ALTER TABLE table_name DROP COLUMN score

--table_name表添加一个叫age的字段,类型为 INTEGER
ALTER TABLE table_name ADD COLUMN age INTEGER

可见,第一种方式的本质就是编写一条 SQL 语句,然后通过 PHP 来执行它。下面,我们来看第二种方式。

第二种方式

有时,我们不满足于让服务器去执行一条 SQL 语句。我们会需要从数据库中查询信息,然后把得到的信息储存起来(其实就是储存在变量中)。这样,我们需要一些额外的工作。先看一坨代码:

<?php

    $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
    $query = "SELECT * FROM table_name WHERE problem_id='$id'";
    $result = mysqli_query($dbc, $query);
    $row = mysqli_fetch_array($result);
    $problem_title = $row['problem_title'];

?>

这里我们省略了 define 语句。

这一坨代码和上一坨的主要区别是,我们使用了 mysqli_query() 函数的返回值,把它保存到 $result 变量中。这个 $result 变量里边保存的即为执行 SELECT 语句的返回结果。

解释一下 SELECT 语句,它的作用是选取 table_name 表中符合 WHERE 子句条件的所有行。上面的语句会选定每一行的所有字段(通配符说明了这一点),并且把这些信息全部储存到变量 $result中。

然后,用变量 $row 储存 mysqli_fetch_array() 函数的返回值。$row 这个变量非常神奇,$row['column_name'] 这个事儿包含的内容正是刚才选定的行的 column_name 字段的值(事实上,$row 正是一个数组)。这里,我们把它赋给了 $problem_title 变量。

到这里你应该问一个问题:如果满足 WHERE 子句条件的有不止一行的话怎么办?要解答这个问题,需要稍微细致的讲解一下 $row 这个事儿。如果满足条件的只有一行,那么使用 $row = mysqli_fetch_array($result) 自然会把这唯一的一行信息储存到 $row 中。如果有很多行,那么第一次使用 $row = mysqli_fetch_array($result) 会把第一行的信息储存到 $row 中,而第二次使用 $row = mysqli_fetch_array($result) 会把第二行的信息储存到 $row 中。如果这时没有下一行了,再次调用的话 $row 会储存逻辑假(false0)。类似,如果符合 WHERE 子句条件的一行都没有,那么执行后 $row 直接存储逻辑假。

最后补充一点刚才没有提到的。如果不需要所有字段的数据,可以只选择需要的字段。方法是把原来 SQL 语句中的通配符换成字段名称。例如:

SELECT problem_name, problem_type FROM table_name WHERE problem_id='$id'

while 循环在 PHP 中的应用举例

如果我们要把一个数据库的许多行信息都展示在网页中,那么需要用到 while 循环和上面的第二种方式。代码如下:

<?php

    $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
    $query = "SELECT user_id FROM database_name ORDER BY user_id ASC";
    $result = mysqli_query($dbc, $query);

    while ($row = mysqli_fetch_array($result)) {
        $user_id = $row['user_id'];
        echo "<tr>";
        echo "<td>".$user_id."</td>";
        echo "</tr>";
    }

?>

如果有一定编程基础的话上面的代码很容易看懂。上面新出现了三种用法,说明如下:

  • SELECT 语句可以附加一个 ORDER BY 子句,用来控制顺序。例如这里是按照字段 user_id 升序排列。下面的例子会先按照 user_rank 降序排列,user_rank 相同时按照 user_id 升序排列:
SELECT user_id, user_rank FROM table_name ORDER BY user_rank DESC, user_id ASC
  • 关于 PHP 中的 echo 语句,它可以用来生成文本,类似于 C 中的 printf() 函数。这里利用它直接生成 HTML 代码。它的用法参考例子就可以了。
  • 关于符号 . 的用法,它的作用是连接字符串(和变量),往往和 echo 配合使用,用法参考示例。

从表单获取信息

概述

这一部分我们演示如何构建一个表单,使用户填写这个表单并把内容储存到数据库。这一技术是用户注册系统和用户互动的基础。

要实现这个功能,需要 HTML 和 PHP 配合完成。HTML 负责表单,而 PHP 负责获取信息并使用 SQL 查询储存信息。首先来看 HTML 部分(就是普通的表单):

<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
    <label for="username">用户名:</label>
    <input type="text" id="username" name="username" /><br/>
    <label for="info">信息:</label>
    <input type="text" id="info" name="info" /><br/>

    <input type="submit" value="Submit" name="submit"/>
</form>

属于 HTML 部分的不再解释了,说一说新鲜的。这里的 action 属性后面的 $_SERVER['PHP_SELF'](严格地说,$_SERVER),是 PHP 的一个超级全局变量,内容是当前页面的相对路径,例如 signup.php。这个 action 属性的含义是指定用户填写的信息在哪里被处理,这里是在当前页面处理。一般的做法都是将负责处理这部分信息的 PHP 代码和 HTML 代码放在同一页面内。

下面来看一下相应的 PHP 处理部分的代码:

<?php

    $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);

    if (isset($_POST['submit'])) {
        $user = $_POST['username'];
        $info = $_POST['info'];
        $query = "INSERT INTO table_name (tb_user, tb_info) VALUES ('$user', '$info')";
        mysqli_query($dbc, $query);	
        echo "<p>提交成功</p>";
    }

    mysqli_close($dbc);

?>

首先仍然是建立数据库连接。当用户点击 sumbit 按钮后,表单的内容会被储存在 PHP 中 $_POST 超级全局变量内,这个超级全局变量仍然是一个数组。isset() 函数用来检查变量是否被设置,只有用户点击 submit 后 isset($_POST['submit']) 才返回真,所以不用担心,首次加载表单(那时用户还没有填写任何内容)是不会执行这部分 PHP 代码的,只有用户提交之后才会执行。用户填写的具体内容可以用 $_POST['name'] 来获取。这里的 name 对应的是 HTML 中 name 属性的内容。这一段程序把用户填写的内容赋给变量,然后执行插入到数据库的操作。

这里新出现了一个内容,就是 mysqli_close() 函数,它的作用是关闭数据库连接。当我们不再需要这个连接的时候,及时关闭是一个好主意。

需要注意的是,这仅仅是最简单的代码,而且实际上是不完善的。如果要真正投入使用,我们需要使它更健壮一些。下面逐一讨论这些内容。

检查用户输入是否合法

如果用户根本没有填写表单,就直接点击提交按钮,会发生什么?在上面的实例中,PHP 依然会乖乖地把空内容插入,而这显然是垃圾信息,不是我们需要的。所以,需要在插入前检查被插入的变量是否为空。例如:

<?php

    if (!empty($user) && !empty($info)) {
        // 插入操作
    }

?>

这里出现了 empty() 函数,用于检查内容是否为空。注意这里使用 isset() 是无效的,因为 isset() 检查的是是否“被设置”,而被设置为空也属于被设置。

错误提示

用户输入有误时,上面的改进除了不执行SQL查询,并没有多少直观上的变化。用户不会收到任何信息表明他们的填写是不合适的。所以我们要在这时产生一些提示,引导用户正确填写表单。

<?php

    if (!empty($user) && !empty($info)) {
        // 插入操作
    } else {
        echo "请填写全部内容后再提交";
    }

?>

防范 SQL 注入攻击

我们执行的 SQL语句中包含变量,执行的时候会直接把变量内容替换进去。而如果攻击者在输入框中输入一些危险的字符(通常包含 SQL 注释符 --,以及其他预先精心设置的内容),就可能导致该次 SQL 查询完全被改写成攻击者需要的意思。为了防范这种攻击,我们需要对可能存在的危险字符进行过滤和转义,较为便捷的方法是使用两个函数。改进后的部分如下:

<?php

    $user = mysqli_real_escape_string($dbc, trim($_POST['username']));
    $info = mysqli_real_escape_string($dbc, trim($_POST['info']));

?>

粘性表单

如果用户第一次填写失败,他们希望能保留已经填写好的内容,只做些修改就好了。这需要使用粘性表单技术。要实现,只需要稍稍改动 HTML 表单部分的代码:

<label for="username">用户名:</label>
<input type="text" id="username" name="user" value="<?php if (!empty($user)) echo $user; ?>" >

显而易见,如果用户填写后因为某些原因没有提交而是回到了这个表单,并且之前填写了 user 字段的内容,那么此时 $user 变量已经被赋值了。那么就会在 HTML 表单显示这些内容,避免用户再次输入。

构造一个注册页面

虽然上面说了很多,但是仅仅满足了我们最基本的输入要求。许多时候我们需要更为复杂的功能。举例来说,要写一个注册页面,必须检查用户名是否重复,还要对密码采取某种技术加密以保证安全。

检查用户是否重复

基本原理就是,根据需要判重的字段(例如用户名)去数据库搜索。如果发现结果则用户名重复,如果没有找到则允许注册。需要一个新函数 mysqli_num_rows(),返回 SELECT 语句得到的行数,根据其是否等于 0 进行判断。

<?php  

    $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);    
    $query = "SELECT * FROM table_name WHERE user_name = '$user'";
    $data = mysqli_query($dbc, $query);
    if (mysqli_num_rows($data) == 0) {
        // 把内容插入数据库
        echo "注册成功";
        mysqli_close($dbc);
        exit();
    } else {
        echo "用户名已被占用,请重新选择用户名";
        $user = "";
    }

?>

$user 清空是为了配合粘性表单。

需要说明的是 exit(); 函数,它会立刻终止 PHP 的运行。因为用户已经注册成功,没有必要执行后面的任何代码,所以使用这个函数。写自己的程序的时候可以亲自试验是否需要这一行、PHP 和 HTML 在 php 中的顺序不同有何影响。我通常的做法是把 PHP 代码放在前面,HTML 代码放在后面。

对密码进行加密存储

明文存储密码是对用户很不负责的,不仅数据库管理员可以看到密码,一旦数据库泄漏,密码就会被公开。所以,我们应该加密存储用户密码。在 PHP 中,可以使用 sha1() 函数进行加密(sha 即 secure hash algorithm 的首字母缩写),它是一种不可逆的加密,加密后会生成定长的一段字符串,并且是无法由这段字符串还原原密码的。

加密的原理是,用户输入密码后,利用 PHP 把 hash 过的密码储存在数据库中。用户登陆的时候,把用户输入的密码进行 hash 运算,之后和数据库中的进行比对。

使用方法如下:

sha1($password)

只注册没有用,必须添加登录功能。登录功能可以使用 Cookie 来实现。这里假定你已经了解 Cookie 的基础知识,只说如何实现。

<?php
    setcookie('user_type', $user_type, time() + (60 * 60 * 24 * 30));
?>

上面的代码用来设置 Cookie,其中函数的第一个参数为 Cookie 名称,第二个参数为数值(这里用一个变量传递),第三个参数为过期时间,单位秒。示例为一个月。

可以用设置多个 Cookie 来存储许多内容,例如用户 ID、用户组(管理员还是普通用户)等。

用户登陆后,我们可以设置一个 Cookie 来存储登录信息(即哪个用户登陆的),然后通过检查这个 Cookie 来设定相应功能。

<?php
    if (isset($_COOKIE['user_type'])) {
        $user_type = $_COOKIE['user_type'];
    }
?>

要删除 Cookie,只需要把过期时间设定在过去。

<?php

    setcookie('user_type', '', time() - 3600);

?>

不要问我为什么设定在过去一个小时,设定几个小时都没问题。

设置 Cookie 有其潜在的危险。由于 Cookie 是保存在用户本地的,所以用户完全可以通过篡改 Cookie 来达到他们的目的。所以,把 Cookie 的值设置得“通俗易懂”不是一个好主意。例如,我们要用 Cookie 来保存登陆的用户名,如果单纯把这个用户名存入 Cookie,那么攻击者会很容易通过修改成他人的用户名来伪造 Cookie 登陆。所以,我们需要其他的手段来防止这一点。

我的做法是,用户注册的时候,把用户名按一定手段进行变换,然后使用 SHA() 函数加密生成一个用户密钥,然后把这个密钥储存进数据库。登陆时,再把这个密钥存储到 Cookie 中,通过检查 Cookie 中的密钥和数据库中用户密钥的匹配情况判定是哪位用户登录。这样,只要你的用户名变换方法不泄露,攻击者就很难按他们的想法伪造 Cookie。

使用 GET 方法

在网页间传递信息除了刚才介绍的 POST 方法外,还有 GET 方法。GET 方法是通过 URL 来完成信息传递的。例如,构造下列网址:

http://www.renfei.org/index.php?id=2

网址最后有 ?id=2 标记。这个信息会储存在$_GET['id'] 这个超级全局变量中,并且可以在 PHP 中使用:

<?php

    if (isset($_GET['id'])) {
        $id = $_GET['id'];
        // code goes there
    }

?>

这个例子中我们把 2 赋给了变量 $id。当然,也可以构造这样的网址:

http://www.renfei.org/index.php?id=2&message=10

除了多一个可以使用的 $_GET['message'] 以外没有任何不同。

这个特性的用处之一就是可以根据网址的不同,配合数据库查询,返回不同的网页内容。例如我做的在线问答系统,就是根据 problem_id 来返回不同题目的。

注意,由于 GET 方法的数值是不可靠的(用户可以手动构造 URL 来传递他们想要的参数),所以应该仅仅用它来做一些无关痛痒的事情(例如显示不同的页面内容)。这里我并没有强调 GET 方法的数值是“透明”的:虽然 POST 方法的数值不会显示在 URL 中,但是它还是会通过 HTTP Header 发送到服务器,用许多插件和小工具都可以查看 HTTP Header 信息。

另外,如果你的表单是用来上传文件的,那么估计你会更喜欢 POST 方法:因为  GET 方法得到的 URL 可能会很长,甚至超过浏览器的限制!

使用模板

最后一部分,来讲一下使用模板构造一个网站。

事实上,网站的每个页面中,有许多部分是完全相同的,例如数据库连接常量(就是那些define语句)以及每一页的 header 和 footer 部分等。这样,我们没必要在每一页内写相同的代码。除了麻烦和浪费空间以外,还有一点很重要的原因,就是修改的时候工作量很大。

PHP 中 require_once 语句作用就是把其他文件的内容插入此处。例如,我们可以创建一个define.php,把define语句全部写到里面,并在每个页面顶部添加如下语句:

<?php

    require_once "define.php";

?>

这样一来,会把 define.php 中的内容插入当前位置。同理,我们可以建立一个 header.phpfooter.php,写好页面的头部、底部之后在每个其他页面导入就可以了。

PHP的错误处理

分级的错误信息

最后来讲一下 PHP 的错误处理机制。如果你写了有错误的 PHP 代码,那么运行的时候系统会自动生成一些错误提示信息并且打印到屏幕上,以提醒用户修复。通常,这些错误信息是分级的。首先,是 notice。如果屏幕出现了 notice: (...) 的提示说明你有需要修复的小问题(你没有完全按照规则进行),不过问题不大,代码还是会继续执行完毕。而 warning 则更严重一些,如果出现 warning,你可能需要思考一下你是否真的知道自己在做什么,并作出修改。但是,程序仍然会运行。如果出现了 error,那么 PHP 是在跟你说:你是个白痴;这种代码无法执行,程序的运行会中止。

在写 PHP 程序的时候,我们需要这些错误提示来帮助我们改正错误,但是当产品发布的时候,开发人员往往倾向于隐藏错误提示:用户收到这些信息是很让人恼火的,而且,让他人知道你的代码有什么漏洞总归不是一个好主意,因为这可能被某些图谋不轨的攻击者加以利用。

Suppression Operator

有时,为了代码的简洁性考虑我们可能会故意犯一些无关痛痒的小错误。例如,如果 $_GET 中的某一个元素不一定总会被提交到 PHP,那么理论上应该使用 isset() 函数来进行检测。但是,如果你觉得到处使用这个函数太麻烦了,可以省略 isset() 函数而直接使用这个元素,只不过如果它没有被设置的话会返回一个 notice 错误信息(类似于 C/C++ 中的变量未声明)。这时,为了忽略这一条信息,可以使用错误抑制操作符 @。例如:

<?php

    if (@$_GET['opt']) {
        // code goes here...
    }

?>

其他提示

  • 尽管没有特别强调,但是有几个函数是需要灵活掌握和使用的,例如 exit()。它可以立刻结束 PHP 程序的运行。例如,有的页面需要一定用户权限才能访问,则可以把验证权限的代码放在页面顶端,如果验证失败则显示错误信息并调用 exit() 函数。
  • 当一个 SQL 连接的使命完成后,不要忘了用 mysqli_close() 关闭它。
  • 设计 SQL 数据库的结构是一件非常重要的事情,设计的原则是高效且便于查询。一旦你的数据库充满各种信息,再想更改它的结构就会变得有些困难。
  • SQL 的知识这里介绍得不多。它有许多特性,比如默认值、主键等。默认值的意思是如果不设定,那么该字段采用默认值;主键则规定该字段每行是不能重复的。默认值除了固定字符以外,还可以设定为时间,甚至自增。例如,要建立一个用户数据库,为每个用户分配一个唯一 ID,则可以把数据库中的 ID 字段设为 AUTO INCREMENT,这样每次不用手工维护这个字段,只要新增一行,这个字段的数值就增 1(默认从 1 开始),很方便。 一般会把这种 ID 字段设为主键。
  • 本来打算简要介绍一下 PHP 和 MySQL 的,但是一写就是 7000 字。即使如此,本文介绍的所有特性也仅仅是构建一个动态网站最基本的知识,而且许多非重要的知识并没有介绍。你应该通过书籍更深入地学习。
  • 额外推荐 PHP 的文档,对新手非常友好,值得一看:http://us3.php.net/manual/en/

Centos升级Python 2.7.12并安装最新pip

shenzt@sina.com阅读(219)

Centos升级Python 2.7.12并安装最新pip

Centos系统一般默认就安装有Python2.6.6版本,不少软件需要2.7以上的,通过包管理工具安装不了最新的版本,通过源码编译可以方便安装指定版本,只需要把下面版本的数字换成你想要的版本号。

1.安装步骤

下载源码

1
wget http://www.python.org/ftp/python/2.7.12/Python-2.7.12.tgz

在下载目录解压源码

1
tar -zxvf Python-2.7.12.tgz

进入解压后的文件夹

1
cd Python-2.7.12

在编译前先在/usr/local建一个文件夹python2.7.12(作为python的安装路径,以免覆盖老的版本,新旧版本可以共存的)

1
mkdir /usr/local/python2.7.12

,编译前需要安装下面依赖,否则下面安装pip就会出错

1
yum install openssl openssl-devel zlib-devel gcc -y

安装完依赖后执行下面命令

1
vim ./Modules/Setup

找到#zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz去掉注释并保存(即去掉井号)

在解压缩后的目录下编译安装

1
2
3
./configure --prefix=/usr/local/python2.7.12 --with-zlib
make
make install

此时没有覆盖老版本,再将原来/usr/bin/python链接改为别的名字

1
mv /usr/bin/python /usr/bin/python2.6.6

再建立新版本python的软链接

1
ln -s /usr/local/python2.7.12/bin/python2.7 /usr/bin/python

这个时候输入
python
就会显示出python的新版本信息

Python 2.7.12 (default, Oct 13 2016, 03:17:14)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-17)] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.

2.修改yum配置文件

之所以要保留旧版本,因为yum依赖Python2.6,改下yum的配置文件,指定旧的Python版本就可以了。

vim /usr/bin/yum,将第一行的#!/usr/bin/python修改成#!/usr/bin/python2.6.6

3.安装最新版本的pip

1
2
wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py

找到pip2.7的路径

1
find / -name "pip*"

上面的命令输出
/root/.cache/pip
这里省略一堆输出
/usr/local/python2.7.12/bin/pip
/usr/local/python2.7.12/bin/pip2
/usr/local/python2.7.12/bin/pip2.7 #就是这个
/usr/bin/pip
/usr/bin/pip2
/usr/bin/pip2.6

为其创建软链作为系统默认的启动版本(之前有旧版本的话就先删掉rm -rf /usr/bin/pip

1
ln -s /usr/local/python2.7.12/bin/pip2.7 /usr/bin/pip

看下pip的版本

1
pip -V

pip 8.1.2 from /usr/local/python2.7.12/lib/python2.7/site-packages (python 2.7)

pip安装完毕,现在可以用它下载安装各种包了

我把上面的所有写成下面简单的脚本,一键就可以升级好。

1
wget http://7xpt4s.com1.z0.glb.clouddn.com/update-python2.7.12.sh && bash update-python2.7.12.sh

参考:

https://ruter.github.io/2015/12/03/Update-python/

https://blog.phpgao.com/pip-easy_install-setuptool.html

CentOS 7 下使用 Firewall

shenzt@sina.com阅读(274)

CentOS 7 下使用 Firewall

在 CentOS 7 中,引入了一个新的服务,Firewalld,下面一张图,让大家明确的了解 Firewall 与 iptables 之间的关系与区别。

firewall stack

安装它,只需

# yum install firewalld

如果需要图形界面的话,则再安装

# yum install firewall-config

一、介绍

防火墙守护 firewalld 服务引入了一个信任级别的概念来管理与之相关联的连接与接口。它支持 ipv4 与 ipv6,并支持网桥,采用 firewall-cmd (command) 或 firewall-config (gui) 来动态的管理 kernel netfilter 的临时或永久的接口规则,并实时生效而无需重启服务。

zone

Firewall 能将不同的网络连接归类到不同的信任级别,Zone 提供了以下几个级别

  • drop: 丢弃所有进入的包,而不给出任何响应
  • block: 拒绝所有外部发起的连接,允许内部发起的连接
  • public: 允许指定的进入连接
  • external: 同上,对伪装的进入连接,一般用于路由转发
  • dmz: 允许受限制的进入连接
  • work: 允许受信任的计算机被限制的进入连接,类似 workgroup
  • home: 同上,类似 homegroup
  • internal: 同上,范围针对所有互联网用户
  • trusted: 信任所有连接
过滤规则
  • source: 根据源地址过滤
  • interface: 根据网卡过滤
  • service: 根据服务名过滤
  • port: 根据端口过滤
  • icmp-block: icmp 报文过滤,按照 icmp 类型配置
  • masquerade: ip 地址伪装
  • forward-port: 端口转发
  • rule: 自定义规则

其中,过滤规则的优先级遵循如下顺序

  1. source
  2. interface
  3. firewalld.conf

二、使用方法

# systemctl start firewalld         # 启动,
# systemctl enable firewalld        # 开机启动
# systemctl stop firewalld          # 关闭
# systemctl disable firewalld       # 取消开机启动

具体的规则管理,可以使用 firewall-cmd,具体的使用方法可以

$ firewall-cmd --help

--zone=NAME                         # 指定 zone
--permanent                         # 永久修改,--reload 后生效
--timeout=seconds                   # 持续效果,到期后自动移除,用于调试,不能与 --permanent 同时使用
1. 查看规则

查看运行状态

$ firewall-cmd --state

查看已被激活的 Zone 信息

$ firewall-cmd --get-active-zones
public
  interfaces: eth0 eth1

查看指定接口的 Zone 信息

$ firewall-cmd --get-zone-of-interface=eth0
public

查看指定级别的接口

$ firewall-cmd --zone=public --list-interfaces
eth0

查看指定级别的所有信息,譬如 public

$ firewall-cmd --zone=public --list-all
public (default, active)
  interfaces: eth0
  sources:
  services: dhcpv6-client http ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

查看所有级别被允许的信息

$ firewall-cmd --get-service

查看重启后所有 Zones 级别中被允许的服务,即永久放行的服务

$ firewall-cmd --get-service --permanent
2. 管理规则
# firewall-cmd --panic-on           # 丢弃
# firewall-cmd --panic-off          # 取消丢弃
# firewall-cmd --query-panic        # 查看丢弃状态
# firewall-cmd --reload             # 更新规则,不重启服务
# firewall-cmd --complete-reload    # 更新规则,重启服务

添加某接口至某信任等级,譬如添加 eth0 至 public,永久修改

# firewall-cmd --zone=public --add-interface=eth0 --permanent

设置 public 为默认的信任级别

# firewall-cmd --set-default-zone=public
a. 管理端口

列出 dmz 级别的被允许的进入端口

# firewall-cmd --zone=dmz --list-ports

允许 tcp 端口 8080 至 dmz 级别

# firewall-cmd --zone=dmz --add-port=8080/tcp

允许某范围的 udp 端口至 public 级别,并永久生效

# firewall-cmd --zone=public --add-port=5060-5059/udp --permanent
b. 网卡接口

列出 public zone 所有网卡

# firewall-cmd --zone=public --list-interfaces

将 eth0 添加至 public zone,永久

# firewall-cmd --zone=public --permanent --add-interface=eth0

eth0 存在与 public zone,将该网卡添加至 work zone,并将之从 public zone 中删除

# firewall-cmd --zone=work --permanent --change-interface=eth0

删除 public zone 中的 eth0,永久

# firewall-cmd --zone=public --permanent --remove-interface=eth0
c. 管理服务

添加 smtp 服务至 work zone

# firewall-cmd --zone=work --add-service=smtp

移除 work zone 中的 smtp 服务

# firewall-cmd --zone=work --remove-service=smtp
d. 配置 external zone 中的 ip 地址伪装

查看

# firewall-cmd --zone=external --query-masquerade

打开伪装

# firewall-cmd --zone=external --add-masquerade

关闭伪装

# firewall-cmd --zone=external --remove-masquerade
e. 配置 public zone 的端口转发

要打开端口转发,则需要先

# firewall-cmd --zone=public --add-masquerade

然后转发 tcp 22 端口至 3753

# firewall-cmd --zone=public --add-forward-port=port=22:proto=tcp:toport=3753

转发 22 端口数据至另一个 ip 的相同端口上

# firewall-cmd --zone=public --add-forward-port=port=22:proto=tcp:toaddr=192.168.1.100

转发 22 端口数据至另一 ip 的 2055 端口上

# firewall-cmd --zone=public --add-forward-port=port=22:proto=tcp:toport=2055:toaddr=192.168.1.100
f. 配置 public zone 的 icmp

查看所有支持的 icmp 类型

# firewall-cmd --get-icmptypes
destination-unreachable echo-reply echo-request parameter-problem redirect router-advertisement router-solicitation source-quench time-exceeded

列出

# firewall-cmd --zone=public --list-icmp-blocks

添加 echo-request 屏蔽

# firewall-cmd --zone=public --add-icmp-block=echo-request [--timeout=seconds]

移除 echo-reply 屏蔽

# firewall-cmd --zone=public --remove-icmp-block=echo-reply
g. IP 封禁
# firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='222.222.222.222' reject"

以上都是一些常用方法,更多高级方法,请参考:

Systemd 入门教程:命令篇

shenzt@sina.com阅读(182)

Systemd 入门教程:命令篇

Systemd 是 Linux 系统工具,用来启动守护进程,已成为大多数发行版的标准配置。

本文介绍它的基本用法,分为上下两篇。今天介绍它的主要命令,下一篇介绍如何用于实战。

一、由来

历史上,Linux 的启动一直采用init进程。

下面的命令用来启动服务。


$ sudo /etc/init.d/apache2 start
# 或者
$ service apache2 start

这种方法有两个缺点。

一是启动时间长。init进程是串行启动,只有前一个进程启动完,才会启动下一个进程。

二是启动脚本复杂。init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这往往使得脚本变得很长。

二、Systemd 概述

Systemd 就是为了解决这些问题而诞生的。它的设计目标是,为系统的启动和管理提供一套完整的解决方案。

根据 Linux 惯例,字母d是守护进程(daemon)的缩写。 Systemd 这个名字的含义,就是它要守护整个系统。

 

使用了 Systemd,就不需要再用init了。Systemd 取代了initd,成为系统的第一个进程(PID 等于 1),其他进程都是它的子进程。


$ systemctl --version

上面的命令查看 Systemd 的版本。

Systemd 的优点是功能强大,使用方便,缺点是体系庞大,非常复杂。事实上,现在还有很多人反对使用 Systemd,理由就是它过于复杂,与操作系统的其他部分强耦合,违反”keep simple, keep stupid”的Unix 哲学

(上图为 Systemd 架构图)

三、系统管理

Systemd 并不是一个命令,而是一组命令,涉及到系统管理的方方面面。

3.1 systemctl

systemctl是 Systemd 的主命令,用于管理系统。


# 重启系统
$ sudo systemctl reboot

# 关闭系统,切断电源
$ sudo systemctl poweroff

# CPU停止工作
$ sudo systemctl halt

# 暂停系统
$ sudo systemctl suspend

# 让系统进入冬眠状态
$ sudo systemctl hibernate

# 让系统进入交互式休眠状态
$ sudo systemctl hybrid-sleep

# 启动进入救援状态(单用户状态)
$ sudo systemctl rescue

3.2 systemd-analyze

systemd-analyze命令用于查看启动耗时。


# 查看启动耗时
$ systemd-analyze                                                                                       

# 查看每个服务的启动耗时
$ systemd-analyze blame

# 显示瀑布状的启动过程流
$ systemd-analyze critical-chain

# 显示指定服务的启动流
$ systemd-analyze critical-chain atd.service

3.3 hostnamectl

hostnamectl命令用于查看当前主机的信息。


# 显示当前主机的信息
$ hostnamectl

# 设置主机名。
$ sudo hostnamectl set-hostname rhel7

3.4 localectl

localectl命令用于查看本地化设置。


# 查看本地化设置
$ localectl

# 设置本地化参数。
$ sudo localectl set-locale LANG=en_GB.utf8
$ sudo localectl set-keymap en_GB

3.5 timedatectl

timedatectl命令用于查看当前时区设置。


# 查看当前时区设置
$ timedatectl

# 显示所有可用的时区
$ timedatectl list-timezones                                                                                   

# 设置当前时区
$ sudo timedatectl set-timezone America/New_York
$ sudo timedatectl set-time YYYY-MM-DD
$ sudo timedatectl set-time HH:MM:SS

3.6 loginctl

loginctl命令用于查看当前登录的用户。


# 列出当前session
$ loginctl list-sessions

# 列出当前登录用户
$ loginctl list-users

# 列出显示指定用户的信息
$ loginctl show-user ruanyf

四、Unit

4.1 含义

Systemd 可以管理所有系统资源。不同的资源统称为 Unit(单位)。

Unit 一共分成12种。

  • Service unit:系统服务
  • Target unit:多个 Unit 构成的一个组
  • Device Unit:硬件设备
  • Mount Unit:文件系统的挂载点
  • Automount Unit:自动挂载点
  • Path Unit:文件或路径
  • Scope Unit:不是由 Systemd 启动的外部进程
  • Slice Unit:进程组
  • Snapshot Unit:Systemd 快照,可以切回某个快照
  • Socket Unit:进程间通信的 socket
  • Swap Unit:swap 文件
  • Timer Unit:定时器

systemctl list-units命令可以查看当前系统的所有 Unit 。


# 列出正在运行的 Unit
$ systemctl list-units

# 列出所有Unit,包括没有找到配置文件的或者启动失败的
$ systemctl list-units --all

# 列出所有没有运行的 Unit
$ systemctl list-units --all --state=inactive

# 列出所有加载失败的 Unit
$ systemctl list-units --failed

# 列出所有正在运行的、类型为 service 的 Unit
$ systemctl list-units --type=service

4.2 Unit 的状态

systemctl status命令用于查看系统状态和单个 Unit 的状态。


# 显示系统状态
$ systemctl status

# 显示单个 Unit 的状态
$ sysystemctl status bluetooth.service

# 显示远程主机的某个 Unit 的状态
$ systemctl -H 7.example.com status httpd.service

除了status命令,systemctl还提供了三个查询状态的简单方法,主要供脚本内部的判断语句使用。


# 显示某个 Unit 是否正在运行
$ systemctl is-active application.service

# 显示某个 Unit 是否处于启动失败状态
$ systemctl is-failed application.service

# 显示某个 Unit 服务是否建立了启动链接
$ systemctl is-enabled application.service

4.3 Unit 管理

对于用户来说,最常用的是下面这些命令,用于启动和停止 Unit(主要是 service)。


# 立即启动一个服务
$ sudo systemctl start apache.service

# 立即停止一个服务
$ sudo systemctl stop apache.service

# 重启一个服务
$ sudo systemctl restart apache.service

# 杀死一个服务的所有子进程
$ sudo systemctl kill apache.service

# 重新加载一个服务的配置文件
$ sudo systemctl reload apache.service

# 重载所有修改过的配置文件
$ sudo systemctl daemon-reload

# 显示某个 Unit 的所有底层参数
$ systemctl show httpd.service

# 显示某个 Unit 的指定属性的值
$ systemctl show -p CPUShares httpd.service

# 设置某个 Unit 的指定属性
$ sudo systemctl set-property httpd.service CPUShares=500

4.4 依赖关系

Unit 之间存在依赖关系:A 依赖于 B,就意味着 Systemd 在启动 A 的时候,同时会去启动 B。

systemctl list-dependencies命令列出一个 Unit 的所有依赖。


$ systemctl list-dependencies nginx.service

上面命令的输出结果之中,有些依赖是 Target 类型(详见下文),默认不会展开显示。如果要展开 Target,就需要使用--all参数。


$ systemctl list-dependencies --all nginx.service

五、Unit 的配置文件

5.1 概述

每一个 Unit 都有一个配置文件,告诉 Systemd 怎么启动这个 Unit 。

Systemd 默认从目录/etc/systemd/system/读取配置文件。但是,里面存放的大部分文件都是符号链接,指向目录/usr/lib/systemd/system/,真正的配置文件存放在那个目录。

systemctl enable命令用于在上面两个目录之间,建立符号链接关系。


$ sudo systemctl enable .service
# 等同于
$ sudo ln -s '/' '/'

如果配置文件里面设置了开机启动,systemctl enable命令相当于激活开机启动。

与之对应的,systemctl disable命令用于在两个目录之间,撤销符号链接关系,相当于撤销开机启动。


$ sudo systemctl disable .service

配置文件的后缀名,就是该 Unit 的种类,比如sshd.socket。如果省略,Systemd 默认后缀名为.service,所以sshd会被理解成sshd.service

5.2 配置文件的状态

systemctl list-unit-files命令用于列出所有配置文件。


# 列出所有配置文件
$ systemctl list-unit-files

# 列出指定类型的配置文件
$ systemctl list-unit-files --type=service

这个命令会输出一个列表。


$ systemctl list-unit-files

UNIT FILE              STATE
chronyd.service        enabled
clamd@.service         static
.service     disabled

这个列表显示每个配置文件的状态,一共有四种。

  • enabled:已建立启动链接
  • disabled:没建立启动链接
  • static:该配置文件没有[Install]部分(无法执行),只能作为其他配置文件的依赖
  • masked:该配置文件被禁止建立启动链接

注意,从配置文件的状态无法看出,该 Unit 是否正在运行。这必须执行前面提到的systemctl status命令。


$ systemctl status bluetooth.service

一旦修改配置文件,就要让 SystemD 重新加载配置文件,然后重新启动,否则修改不会生效。


$ sudo systemctl daemon-reload
$ sudo systemctl restart httpd.service

5.3 配置文件的格式

配置文件就是普通的文本文件,可以用文本编辑器打开。

systemctl cat命令可以查看配置文件的内容。


$ systemctl cat atd.service

[Unit]
Description=ATD daemon

[Service]
Type=forking
ExecStart=/usr/bin/atd

[Install]
WantedBy=multi-user.target

从上面的输出可以看到,配置文件分成几个区块。每个区块的第一行,是用方括号表示的区别名,比如[Unit]。注意,配置文件的区块名和字段名,都是大小写敏感的。

每个区块内部是一些等号连接的键值对。


[Section]
Directive1=value
Directive2=value

. . .

注意,键值对的等号两侧不能有空格。

5.4 配置文件的区块

[Unit]区块通常是配置文件的第一个区块,用来定义 Unit 的元数据,以及配置与其他 Unit 的关系。它的主要字段如下。

  • Description:简短描述
  • Documentation:文档地址
  • Requires:当前 Unit 依赖的其他 Unit,如果它们没有运行,当前 Unit 会启动失败
  • Wants:与当前 Unit 配合的其他 Unit,如果它们没有运行,当前 Unit 不会启动失败
  • BindsTo:与Requires类似,它指定的 Unit 如果退出,会导致当前 Unit 停止运行
  • Before:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之后启动
  • After:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之前启动
  • Conflicts:这里指定的 Unit 不能与当前 Unit 同时运行
  • Condition...:当前 Unit 运行必须满足的条件,否则不会运行
  • Assert...:当前 Unit 运行必须满足的条件,否则会报启动失败

[Install]通常是配置文件的最后一个区块,用来定义如何启动,以及是否开机启动。它的主要字段如下。

  • WantedBy:它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system目录下面以 Target 名 + .wants后缀构成的子目录中
  • RequiredBy:它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入/etc/systemd/system目录下面以 Target 名 + .required后缀构成的子目录中
  • Alias:当前 Unit 可用于启动的别名
  • Also:当前 Unit 激活(enable)时,会被同时激活的其他 Unit

[Service]区块用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。它的主要字段如下。

  • Type:定义启动时的进程行为。它有以下几种值。
  • Type=simple:默认值,执行ExecStart指定的命令,启动主进程
  • Type=forking:以 fork 方式从父进程创建子进程,创建后父进程会立即退出
  • Type=oneshot:一次性进程,Systemd 会等当前服务退出,再继续往下执行
  • Type=dbus:当前服务通过D-Bus启动
  • Type=notify:当前服务启动完毕,会通知Systemd,再继续往下执行
  • Type=idle:若有其他任务执行完毕,当前服务才会运行
  • ExecStart:启动当前服务的命令
  • ExecStartPre:启动当前服务之前执行的命令
  • ExecStartPost:启动当前服务之后执行的命令
  • ExecReload:重启当前服务时执行的命令
  • ExecStop:停止当前服务时执行的命令
  • ExecStopPost:停止当其服务之后执行的命令
  • RestartSec:自动重启当前服务间隔的秒数
  • Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括always(总是重启)、on-successon-failureon-abnormalon-aborton-watchdog
  • TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数
  • Environment:指定环境变量

Unit 配置文件的完整字段清单,请参考官方文档

六、Target

启动计算机的时候,需要启动大量的 Unit。如果每一次启动,都要一一写明本次启动需要哪些 Unit,显然非常不方便。Systemd 的解决方案就是 Target。

简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。从这个意义上说,Target 这个概念类似于”状态点”,启动某个 Target 就好比启动到某种状态。

传统的init启动模式里面,有 RunLevel 的概念,跟 Target 的作用很类似。不同的是,RunLevel 是互斥的,不可能多个 RunLevel 同时启动,但是多个 Target 可以同时启动。


# 查看当前系统的所有 Target
$ systemctl list-unit-files --type=target

# 查看一个 Target 包含的所有 Unit
$ systemctl list-dependencies multi-user.target

# 查看启动时的默认 Target
$ systemctl get-default

# 设置启动时的默认 Target
$ sudo systemctl set-default multi-user.target

# 切换 Target 时,默认不关闭前一个 Target 启动的进程,
# systemctl isolate 命令改变这种行为,
# 关闭前一个 Target 里面所有不属于后一个 Target 的进程
$ sudo systemctl isolate multi-user.target

Target 与 传统 RunLevel 的对应关系如下。


Traditional runlevel      New target name     Symbolically linked to...

Runlevel 0           |    runlevel0.target -> poweroff.target
Runlevel 1           |    runlevel1.target -> rescue.target
Runlevel 2           |    runlevel2.target -> multi-user.target
Runlevel 3           |    runlevel3.target -> multi-user.target
Runlevel 4           |    runlevel4.target -> multi-user.target
Runlevel 5           |    runlevel5.target -> graphical.target
Runlevel 6           |    runlevel6.target -> reboot.target

它与init进程的主要差别如下。

(1)默认的 RunLevel(在/etc/inittab文件设置)现在被默认的 Target 取代,位置是/etc/systemd/system/default.target,通常符号链接到graphical.target(图形界面)或者multi-user.target(多用户命令行)。

(2)启动脚本的位置,以前是/etc/init.d目录,符号链接到不同的 RunLevel 目录 (比如/etc/rc3.d/etc/rc5.d等),现在则存放在/lib/systemd/system/etc/systemd/system目录。

(3)配置文件的位置,以前init进程的配置文件是/etc/inittab,各种服务的配置文件存放在/etc/sysconfig目录。现在的配置文件主要存放在/lib/systemd目录,在/etc/systemd目录里面的修改可以覆盖原始设置。

七、日志管理

Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用journalctl一个命令,查看所有日志(内核日志和应用日志)。日志的配置文件是/etc/systemd/journald.conf

journalctl功能强大,用法非常多。


# 查看所有日志(默认情况下 ,只保存本次启动的日志)
$ sudo journalctl

# 查看内核日志(不显示应用日志)
$ sudo journalctl -k

# 查看系统本次启动的日志
$ sudo journalctl -b
$ sudo journalctl -b -0

# 查看上一次启动的日志(需更改设置)
$ sudo journalctl -b -1

# 查看指定时间的日志
$ sudo journalctl --since="2012-10-30 18:17:16"
$ sudo journalctl --since "20 min ago"
$ sudo journalctl --since yesterday
$ sudo journalctl --since "2015-01-10" --until "2015-01-11 03:00"
$ sudo journalctl --since 09:00 --until "1 hour ago"

# 显示尾部的最新10行日志
$ sudo journalctl -n

# 显示尾部指定行数的日志
$ sudo journalctl -n 20

# 实时滚动显示最新日志
$ sudo journalctl -f

# 查看指定服务的日志
$ sudo journalctl /usr/lib/systemd/systemd

# 查看指定进程的日志
$ sudo journalctl _PID=1

# 查看某个路径的脚本的日志
$ sudo journalctl /usr/bin/bash

# 查看指定用户的日志
$ sudo journalctl _UID=33 --since today

# 查看某个 Unit 的日志
$ sudo journalctl -u nginx.service
$ sudo journalctl -u nginx.service --since today

# 实时滚动显示某个 Unit 的最新日志
$ sudo journalctl -u nginx.service -f

# 合并显示多个 Unit 的日志
$ journalctl -u nginx.service -u php-fpm.service --since today

# 查看指定优先级(及其以上级别)的日志,共有8级
# 0: emerg
# 1: alert
# 2: crit
# 3: err
# 4: warning
# 5: notice
# 6: info
# 7: debug
$ sudo journalctl -p err -b

# 日志默认分页输出,--no-pager 改为正常的标准输出
$ sudo journalctl --no-pager

# 以 JSON 格式(单行)输出
$ sudo journalctl -b -u nginx.service -o json

# 以 JSON 格式(多行)输出,可读性更好
$ sudo journalctl -b -u nginx.serviceqq
 -o json-pretty

# 显示日志占据的硬盘空间
$ sudo journalctl --disk-usage

# 指定日志文件占据的最大空间
$ sudo journalctl --vacuum-size=1G

# 指定日志文件保存多久
$ sudo journalctl --vacuum-time=1years

(完)

ssh修改登录端口禁止密码登录并免密登录

shenzt@sina.com阅读(302)

1.修改ssh登录端口

1.1 登录远程linux主机:

#linux:

$ ssh user@ip -p port
#windows git-bash:

# ssh user@ip port

1.2 修改ssh登录端口

#以下操作在远程linux主机中操作:

$ vi /etc/ssh/sshd_config

找到sshd_config文件中如下选项并修改:

#Port 22

#修改为:

Port 60022 #这里修改为你想要设置的端口,以60022为例

1.3 修改防火墙配置

$ vi /etc/sysconfig/iptabels

添加以下规则

-A INPUT -m state --state NEW -m tcp -p tcp --dport 60022 -j ACCEPT

修改完成后,刷新iptables并重启ssh服务

$ systemctl restart iptables.service
$ systemctl restart sshd.service

此时如果再使用22端口进行ssh连接,就会报错,用60022端口连接才可以建立。

2.免密登录

SSH免密登录利用了rsa密钥对匹配的原理,可以允许用户从本地不用密码就可以访问到远程主机,让我们来看看怎么做。

2.1 本地生成密钥对

# 在本机命令行控制台输入:

$ ssh-keygen

会有提示,连续按三次回车。

此时会在系统用户的.ssh目录下生成一对密钥文件:私钥文件id_rsa和公钥文件id_rsa_pub。

2.2 将本地公钥内容追加到远程主机的授权文件(authorized_keys)中

本地查看id_rsa_pub文件内容:

$ cat ~/.ssh/id_rsa_pub

复制得到的公钥字符串,在远程服务器上编辑authorized_keys文件:

$ vi .ssh/authorized_keys

将刚刚得到的本地公钥字符串添加到该文件的末尾(如果是新建的文件就直接添加)

编辑保存完成后,修改该文件的权限:

$chmod 600 .ssh/authorized_keys

2.3 修改ssh配置

编辑远程服务器上的sshd_config文件:

$vi /etc/ssh/sshd_config

找到如下选项并修改(通常情况下,前两项默认为no,地三项如果与此处不符,以此处为准):

#启用密钥验证
RSAAuthentication yes
PubkeyAuthentication yes
#指定公钥数据库文件
AuthorsizedKeysFile.ssh/authorized_keys

编辑保存完成后,重启ssh服务使得新配置生效:

对于centos7,使用以下命令:
$ systemctl restart sshd.service
对于centos6,使用以下命令:
$ service sshd restart
此时,就可以通过ssh命令免除密码直接登录远程主机了,在本地命令行控制台输入:
$ ssh user@ip -p 60022

就可以了(第一次需要输入密码,以后就不用了)

3. 禁止SSH口令登录

为了安全性更高,我们既然已经使用了密钥免密登录,那么就可以直接禁止再使用口令来连接SSH远程主机了。

3.1 更改ssh配置

编辑远程服务器上的sshd_config文件:

$vi /etc/ssh/sshd_config

找到如下选项并修改(通常情况下,前两项默认为no,地三项如果与此处不符,以此处为准):

#PasswordAuthentication yes 改为
PasswordAuthentication no

编辑保存完成后,重启ssh服务使得新配置生效,然后就无法使用口令来登录ssh了

$ systemctl restart sshd.service

CentOS升级Python2.6到Python2.7并安装pip

shenzt@sina.com阅读(260)

CentOS升级Python2.6到Python2.7并安装pip

0. 依赖安装

1
2
3
4
5
yum -y update
yum install epel-release
yum install sqlite-devel
yum install -y zlib-devel.x86_64
yum install -y openssl-devel.x86_64

1. 升级Python

系统默认安装的Python是2.6.6的,我们需要升级到Python2.7,用wget命令从官方下载源文件,然后解压进行编译

1
2
3
wget http://www.python.org/ftp/python/2.7.10/Python-2.7.10.tar.xz
unxz Python-2.7.10.tar.xz
tar -vxf Python-2.7.10.tar

执行完以上命令会解压得到Python-2.7.10这个文件夹,进入该目录并执行以下命令进行配置

1
./configure enableshared enableloadablesqliteextensions withzlib

其中--enable-loadable-sqlite-extensions是sqlite的扩展,如果需要使用的话则带上这个选项。

之后执行

1
vi ./Modules/Setup

找到#zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz去掉注释并保存,然后进行编译和安装

1
make && make install

安装好Python2.7之后我们需要先把Python2.6备份起来,然后再对yum的配置进行修改,如果不进行这一步操作的话,执行yum命令将会提示你Python的版本不对。

执行以下命令,对Python2.6进行备份,然后为Python2.7创建软链接

1
2
mv /usr/bin/python /usr/bin/python2.6.6
ln -s /usr/local/bin/python2.7 /usr/bin/python

然后编辑/usr/bin/yum,将第一行的#!/usr/bin/python修改成#!/usr/bin/python2.6.6
现在执行yum命令已经不会出现之前的错误信息了。

我们执行python -V查看版本信息,如果出现错误

error while loading shared libraries: libpython2.7.so.1.0: cannot open shared object file: No such file or directory

编辑配置文件

1
vi /etc/ld.so.conf

添加新的一行内容/usr/local/lib,保存退出,然后

1
2
/sbin/ldconfig
/sbin/ldconfig -v

2. 安装pip

下载最新版的pip,然后安装

1
2
wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py

查找pip的位置

1
whereis pip

找到pip2.7的路径,为其创建软链作为系统默认的启动版本

1
ln -s /usr/local/bin/pip2.7 /usr/bin/pip

pip安装完毕,现在可以用它下载安装各种包了 🙂

配置Nginx和uWSGI搭建Django运行环境

顶好爱迪 更专业 更方便

联系我们联系我们