APP生成签名

MAC下 Android签名生成keystore

1.生成证书

在终端输入
keytool -genkey -v -keystore android.keystore -alias android -keyalg RSA -validity 20000 -keystore /Users/当前用户的用户名/android_demo.keystore
如果mac没有安装Java JDK 则会提示如下信息:

安装完成之后再次在终端输入上面的命令,按照要求(如下图)填写信息.最后一个检验信息一定要填写:y 而不是:yes .网上大部分都是写的填写: yes  导致我尝试很多次一直在重复填写信息那一步.

填写信息完成之后,证书创建就完成了. 上面输入的命令里面的/Users/当前用户的用户名/android_demo.keystore 就是证书的地址.

2.查看证书信息

在终端输入命令:

keytool -list -v -keystore 证书存放地址(例如: /Users/当前用户的用户名/android_demo.keystore)

回车.输入刚才的口令密码,即可查看证书的所有信息(例如申请一些三方需要的SHA1).

 

Android平台签名证书(.keystore)生成指南

分类:HTML5+
Android证书
Android平台打包发布apk应用,需要使用数字证书(.keystore文件)进行签名,用于表明开发者身份。Android证书的生成是自助和免费的,不需要审批或付费。可以使用JRE环境中的keytool命令生成。以下是windows平台生成证书的方法:

安装JRE环境(推荐使用JRE8环境,如已有可跳过)

可从Oracle官方下载jre安装包:https://www.oracle.com/technetwork/java/javase/downloads/index.html
下面以安装目录为“C:\Program Files\Java\jre1.8.0_201”为例,实际操作时请修改为自己安装目录
建议将JRE安装路径添加到系统环境变量,已配置可跳过此章节
打开命令行(cmd),输入以下命令:

在终端输入命令:  
set PATH=%PATH%;"C:\Program Files\Java\jre1.8.0_201\bin"
  • 第一行:切换工作目录到D:路径
  • 第二行:将jre命令添加到临时环境变量中

生成签名证书

使用keytool -genkey命令生成证书:

在终端输入命令: keytool -genkey -alias testalias -keyalg RSA -keysize 2048 -validity 36500 -keystore test.keystore
  • testalias是证书别名,可修改为自己想设置的字符,建议使用英文字母和数字
  • test.keystore是证书文件名称,可修改为自己想设置的文件名称,也可以指定完整文件路径

回车后会提示:

在终端输入命令:Enter keystore password:  //输入证书文件密码,输入完成回车  
Re-enter new password:   //再次输入证书文件密码,输入完成回车  
What is your first and last name?  
  [Unknown]:  //输入名字和姓氏,输入完成回车  
What is the name of your organizational unit?  
  [Unknown]:  //输入组织单位名称,输入完成回车  
What is the name of your organization?  
  [Unknown]:  //输入组织名称,输入完成回车  
What is the name of your City or Locality?  
  [Unknown]:  //输入城市或区域名称,输入完成回车  
What is the name of your State or Province?  
  [Unknown]:  //输入省/市/自治区名称,输入完成回车  
What is the two-letter country code for this unit?  
  [Unknown]:  //输入国家/地区代号(两个字母),中国为CN,输入完成回车  
Is CN=XX, OU=XX, O=XX, L=XX, ST=XX, C=XX correct?  
  [no]:  //确认上面输入的内容是否正确,输入y,回车  

Enter key password for <testalias>  
        (RETURN if same as keystore password):  //确认证书密码与证书文件密码一样(HBuilder|HBuilderX要求这两个密码一致),直接回车就可以

以上命令运行完成后就会生成证书,路径为“D:\test.keystore”。

查看证书信息

可以使用以下命令查看:

在终端输入命令:keytool -list -v -keystore test.keystore  
Enter keystore password: //输入密码,回车

会输出以下格式信息:

在终端输入命令:Keystore type: PKCS12    
Keystore provider: SUN    

Your keystore contains 1 entry    

Alias name: test    
Creation date: 2019-10-28    
Entry type: PrivateKeyEntry    
Certificate chain length: 1    
Certificate[1]:    
Owner: CN=Tester, OU=Test, O=Test, L=HD, ST=BJ, C=CN    
Issuer: CN=Tester, OU=Test, O=Test, L=HD, ST=BJ, C=CN    
Serial number: 7dd12840    
Valid from: Fri Jul 26 20:52:56 CST 2019 until: Sun Jul 02 20:52:56 CST 2119    
Certificate fingerprints:    
         MD5:  F9:F6:C8:1F:DB:AB:50:14:7D:6F:2C:4F:CE:E6:0A:A5    
         SHA1: BB:AC:E2:2F:97:3B:18:02:E7:D6:69:A3:7A:28:EF:D2:3F:A3:68:E7    
         SHA256: 24:11:7D:E7:36:12:BC:FE:AF:2A:6A:24:BD:04:4F:2E:33:E5:2D:41:96:5F:50:4D:74:17:7F:4F:E2:55:EB:26    
Signature algorithm name: SHA256withRSA    
Subject Public Key Algorithm: 2048-bit RSA key    
Version: 3

其中证书指纹信息(Certificate fingerprints):

  • MD5
    证书的MD5指纹信息(安全码MD5)
  • SHA1
    证书的SHA1指纹信息(安全码SHA1)
  • SHA256
    证书的SHA256指纹信息(安全码SHA245)

 

1、修改keystore密码的命令(keytool为JDK带的命令行工具):

keytool -storepasswd -keystore my.keystore

2、修改keystore的alias(别名):

keytool -changealias -keystore my.keystore -alias my_name_key -destalias aliasdebugkey

3、修改alias(别名)的密码:

keytool -keypasswd -keystore my.keystore -alias aliasdebugkey

LNMP环境为PHP添加exif扩展

在使用时 php报出如下错误: Call to undefined function gemvary\exif_imagetype()

好吧,exif扩展没安装…

通过 打印phpinfo() 查看得知 mbstring 扩展是有的,exif扩展没有

982daa5b6884e1aaa66c1558ae324394.png

如果mbstring也没有,也可以参考以下exif扩展的安装过程;

安装过程基本类似的;

进入主题:

1、查看当前环境PHP的版本号和安装目录

whereis php
结果:
[root@xiaojun exif]# whereis php
php: /usr/bin/php /usr/lib64/php /etc/php.d /etc/php.ini /usr/include/php /usr/local/php /usr/share/php /usr/local/php/bin/php /usr/share/man/man1/php.1.gz

[root@xiaojun exif]# /usr/local/php/bin/php -v
PHP 7.1.7 (cli) (built: Mar 16 2018 11:06:26) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

那么phpize的位置就是 /usr/local/php/bin/phpize

2、进入php的源码目录

#这是我电脑上的路径,得改成自己服务器上的路径
cd /www/lnmp1.4/src/php-7.1.7/ext/exif

进入扩展目录后进行初始化:

/usr/local/php/bin/phpize

命令执行后当前目录会多几个文件,只要有 configure 这个文件就行

然后再检查配置,输入:

./configure --with-php-config=/usr/local/php/bin/php-config

如果有报错说明路径不对,使用 whereis php-config 查看服务器上此文件的路径

接下来再依次执行这两个命令:

make
make install

执行完会有类似如下信息:

[root@xiaojun exif]# make install
Installing shared extensions:     /usr/local/php/lib/php/extensions/no-debug-non-zts-20160303/

这个目录就是扩展安装后的存放目录;

3、修改php.ini引入扩展

vi /usr/local/php/etc/php.ini

在最后面加入:

extension=exif.so

然后保存,重启PHP就完事了;

需要注意的是 exif.so 必须放在 mbstring.so 的后面,否则会出错;

可能出现的问题:

重启PHP时提示: NOTICE: PHP message: PHP Warning:  Module ‘mbstring’ already loaded in Unknown on line 0

意思是mbstring这个扩展已经加载过了,还尝试引入;

解决办法:

PHP加载模块有两种方式,一种是通过php.ini 加载模块,另一种是通过编译时的参数加载模块。

这里出这个提示,那么mbstring应该就是属于后者,只需要php.ini中将其注释掉就行了

;extension=mbstring.so

输入/usr/local/bin/phpize后提示: Cannot find config.m4. Make sure that you run /usr/local/bin/phpize in the top level sourc

我是将openssl扩展内的config0.m4文件改成config.m4就没提示了;

cd ../openssl
cp ./config0.m4 ./config.m4

至于为什么openssl扩展的config.m4为什么会影响到安装其它扩展,暂不得而知;

MySQL – binlog日志简介及设置

前言

mysql-binlog是MySQL数据库的二进制日志,用于记录用户对数据库操作的SQL语句((除了数据查询语句)信息。可以使用mysqlbin命令查看二进制日志的内容。

MySQL binlog格式

binlog的格式也有三种:STATEMENT、ROW、MIXED 。

1、STATMENT模式:基于SQL语句的复制(statement-based replication, SBR),每一条会修改数据的sql语句会记录到binlog中。

优点:不需要记录每一条SQL语句与每行的数据变化,这样子binlog的日志也会比较少,减少了磁盘IO,提高性能。

缺点:在某些情况下会导致master-slave中的数据不一致(如sleep()函数, last_insert_id(),以及user-defined functions(udf)等会出现问题)

2、基于行的复制(row-based replication, RBR):不记录每一条SQL语句的上下文信息,仅需记录哪条数据被修改了,修改成了什么样子了。

优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题。

缺点:会产生大量的日志,尤其是alter table的时候会让日志暴涨。

3、混合模式复制(mixed-based replication, MBR):以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择日志保存方式。

binlog配置

在MySQL配置文件my.cnf文件中的mysqld节中添加下面的配置文件:

[mysqld]

#设置日志格式

binlog_format = mixed

#设置日志路径,注意路经需要mysql用户有权限写

log-bin = /data/mysql/logs/mysql-bin.log

#设置binlog清理时间

expire_logs_days = 7

#binlog每个日志文件大小

max_binlog_size = 100m

#binlog缓存大小

binlog_cache_size = 4m

#最大binlog缓存大小

max_binlog_cache_size = 512m

重启MySQL生效,如果不方便重启服务,也可以直接修改对应的变量即可。

总结

无论是增量备份还是主从复制,都是需要开启mysql-binlog日志,最好跟数据目录设置到不同的磁盘分区,可以降低io等待,提升性能;并且在磁盘故障的时候可以利用mysql-binlog恢复数据。

mac pro 如何让终端默认运行python3.X而不是2.7

Mac版本的Python默认是2.7,安装高版本后需要修改为你安装的版本。

1,首先打开终端

open ~/.bash_profile

打开配置文件

2. 写入python的外部环境变量

export PATH=${PATH}:/Library/Frameworks/Python.framework/Versions/3.7/bin

3.重命名python

alias python=”/Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7″

(这步很重要,直接关系到默认启动的python版本是否修改)

4.关闭文件后,在终端调用 source ~/.bash_profile

5.在终端调用 python,查看是否修改成功

 

XlsxWriter的使用

1.优点

一、功能比较强

相对而言,这是除Excel自身之外功能最强的工具了。比如我就用到了它提供的:字体设置、前景色背景色、border设置、视图缩放(zoom)、单元格合并、autofilter、freeze panes、公式、data validation、单元格注释、行高和列宽设置等等。

二、支持大文件写入

如果数据量非常大,可以启用constant memory模式,这是一种顺序写入模式,得到一行数据就立刻写入一行,而不会把所有的数据都保持在内存中。

2.缺点

一、不支持读取和修改

作者并没有打算做一个XlsxReader来提供读取操作。不能读取,也就无从修改了。它只能用来创建新的文件。我是利用xlrd把需要的信息读入后,用XlsxWriter创建全新的文件。

另外,即使是创建到一半Excel文件,也是无法读取已经创建出来的内容的(信息应该在,但是并没有相应的接口)。因为它的主要方法是write而不是set。当你在某个单元格写入数据后,除非你自己保存了相关的内容,否则还是没有办法读出已经写入的信息。从这个角度看,你无法做到读出->修改->写回,只能是写入->写入->写入。

二、不支持XLS文件

XLS是Office 2013或更早版本所使用的格式,是一种二进制格式的文件。XLSX则是用一系列XML文件组成的(最后的X代表了XML)一个压缩包。如果非要创建低版本的XLS文件,就请移步xlwt吧。

三、暂时不支持透视表(Pivot Table

3.基本操作方法

  • 创建excel文件
import xlsxwriter

f = xlsxwriter.Workbook()    # 创建excel文件

  • 创建工作表
worksheet1 = f.add_worksheet('操作日志')  # 括号内为工作表表名

  • 添加工作表样式

样式有很多属性,更多具体样式请参考官方文档。

bold = f.add_format({
        'bold':  True,  # 字体加粗
        'border': 1,  # 单元格边框宽度
        'align': 'left',  # 水平对齐方式
        'valign': 'vcenter',  # 垂直对齐方式
        'fg_color': '#F4B084',  # 单元格背景颜色
        'text_wrap': True,  # 是否自动换行
    })

  • 写入单个单元格数据
//row:行, col:列, data:要写入的数据, bold:单元格的样式
worksheet1.write(row, col, data, bold)

  • 写入一整行,一整列
// A1:从A1单元格开始插入数据,按行插入, data:要写入的数据(格式为一个列表), bold:单元格的样式
worksheet1.write_row(“A1”,data,bold)

// A1:从A1单元格开始插入数据,按列插入, data:要写入的数据(格式为一个列表), bold:单元格的样式
worksheet1.write_column(“A1”,data,bold)

  • 插入图片
// 第一个参数是插入的起始单元格,第二个参数是图片你文件的绝对路径
worksheet1.insert_image('A1','f:\\1.jpg')

  • 写入超链接
worksheet1.write_url(row, col, "internal:%s!A1" % ("要关联的工作表表名"), string="超链接显示的名字")

  • 插入图表
workbook.add_chartsheet(type="")

参数中的type指的是图表类型,图表类型示例如下:
[area:面积图,bar:条形图,column:直方图,doughnut:环状图,line:折线图,pie:饼状图,scatter:散点图,radar:雷达图,stock:箱线图]

  • 获得当前excel文件的所有工作表
workbook.worksheets()

workbook.worksheets()用于获得当前工作簿中的所有工作表,这个函数的存在便利了对于工作表的循环操作,如果你想在当前工作簿的所有工作表的A1单元格中输入一个字符创‘Hello xlsxwriter’,那么这个命令就派上用场了。

  • 关闭excel文件
workbook.close()

这个命令是使用xlsxwriter操作Excel的最后一条命令,一定要记得关闭文件。

Mac下配置PHP+Nginx+Redis环境

Mac下是自己安装了Apache+PHP的,但是Mac OS版本每次变更后都需要重新配置下环境,参考:Mac升级系统macOS Sierra后PHP不编译

1.安装Homebrew

Mac没有预装 Homebrew,安装Homebrew 在终端执行:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

如果提示安装xcode命令行工具,在App Store中下载最新Xcode,然后根据提示安装xcode命令行工具,终端输入:

xcode-select --install

成功后继续安装Homebrew

2.安装Nginx

成功安装brew后,在终端执行:

brew install nginx

安装成功后,查看nginx信息,在终端执行:

brew info nginx

以下为提示信息:
nginx: stable 1.12.2 (bottled), devel 1.13.6, HEAD
...
...
Docroot is: /usr/local/var/www

The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that
nginx can run without sudo.

nginx will load all files in /usr/local/etc/nginx/servers/.

To have launchd start nginx now and restart at login:
  brew services start nginx
Or, if you don't want/need a background service you can just run:
  nginx

Mac是自带Apache的,和Nginx会冲突吗?答案是不会,因为默认端口不同,Apache默认80端口,Nginx默认8080端口
ok,终端执行:

sudo nginx

浏览器访问:localhost:8080

Nginx相关命令

//启动 nginx服务
sudo nginx

//重新加载配置|重启|停止|退出 nginx
nginx -s reload|reopen|stop|quit

//测试配置是否有语法错误
nginx -t
3.安装PHP56

macOSX自带PHP,会跟随系统升级,目前macOS v10.13.x 跟随PHP已经是PHP7.0,所以我们还是需要安装PHP56,执行:

brew install php56 --build-from-source

安装成功,提示:

The php.ini file can be found in:
    /usr/local/etc/php/5.6/php.ini

✩✩✩✩ Extensions ✩✩✩✩

If you are having issues with custom extension compiling, ensure that you are using the brew version, by placing /usr/local/bin before /usr/sbin in your PATH:

      PATH="/usr/local/bin:$PATH"

PHP56 Extensions will always be compiled against this PHP. Please install them using --without-homebrew-php to enable compiling against system PHP.

✩✩✩✩ PHP CLI ✩✩✩✩

If you wish to swap the PHP you use on the command line, you should add the following to ~/.bashrc, ~/.zshrc, ~/.profile or your shell's equivalent configuration file:
  export PATH="$(brew --prefix homebrew/php/php56)/bin:$PATH"

✩✩✩✩ FPM ✩✩✩✩

To launch php-fpm on startup:
    mkdir -p ~/Library/LaunchAgents
    cp /usr/local/opt/php56/homebrew.mxcl.php56.plist ~/Library/LaunchAgents/
    launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php56.plist

The control script is located at /usr/local/opt/php56/sbin/php56-fpm

OS X 10.8 and newer come with php-fpm pre-installed, to ensure you are using the brew version you need to make sure /usr/local/sbin is before /usr/sbin in your PATH:

  PATH="/usr/local/sbin:$PATH"

You may also need to edit the plist to use the correct "UserName".

Please note that the plist was called 'homebrew-php.josegonzalez.php56.plist' in old versions of this formula.

With the release of macOS Sierra the Apache module is now not built by default. If you want to build it on your system you have to install php with the --with-httpd option. See  brew options php56 for more details.

To have launchd start homebrew/php/php56 now and restart at login:
  brew services start homebrew/php/php56

配置php.ini

sudo vim /usr/local/etc/php/5.6/php.ini

设置开机启动php-fpm:

mkdir -p ~/Library/LaunchAgents
cp /usr/local/opt/php56/homebrew.mxcl.php56.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php56.plist

php56-fpm 启动/停止… :

/usr/local/opt/php56/sbin/php56-fpm {start|stop|force-quit|restart|reload|status}

现在我们先执行php56 -v来查看版本要怎么办呢?执行:

sudo ln -s /usr/local/Cellar/php56/5.6.32_8/bin/php /usr/local/bin/php56

设置一下符号链接(相当于windows快捷方式) ,现在php56直接指向了/usr/local/Cellar/php56/5.6.32_8/bin/php 【参考链接】Linux环境变量和符号链接
设置完成,查看PHP版本:

php56 -v
4. 安装Redis

终端执行:

brew search redis

查询结果:
hiredis                       homebrew/php/php56-redis      redis                         redis@3.2
homebrew/php/php53-redis      homebrew/php/php70-redis      redis-leveldb
homebrew/php/php54-redis      homebrew/php/php71-redis      redis@2.6
homebrew/php/php55-redis      homebrew/php/php72-redis      redis@2.8

然后(注意区分下php的redis扩展)

brew install redis
To have launchd start redis now and restart at login:
  brew services start redis
Or, if you don't want/need a background service you can just run:
  redis-server /usr/local/etc/redis.conf

开启redis:

redis-server /usr/local/etc/redis.conf

微信开发服务器返回错误码大全

在微信官方的文档中, 提及的错误码及其说明并不完整, 这里是一个较为完整的错误码.

'-1' => '系统繁忙,此时请开发者稍候再试',
'0' => '请求成功',
'40073' => '不合法的 cardid',
'40009' => '图片文件超长。',
'40013' => '不合法的Appid,请开发者检查AppID的正确性,避免异常字符,注意大小写。',
'40053' => '不合法的actioninfo,请开发者确认参数正确。',
'40071' => '不合法的卡券类型。',
'40072' => '不合法的编码方式。',
'40078' => '不合法的卡券状态。',
'40079' => '不合法的时间。',
'40080' => '不合法的CardExt。',
'40099' => '卡券已被核销。',
'40100' => '不合法的时间区间。',
'40116' => '不合法的Code码。',
'40122' => '不合法的库存数量。',
'40124' => '会员卡设置查过限制的 custom_field字段。',
'40127' => '卡券被用户删除或转赠中。',
'41012' => '缺少cardid参数。',
'45030' => '该cardid无接口权限。',
'45031' => '库存为0。',
'45033' => '用户领取次数超过限制get_limit',
'41011' => '缺少必填字段。',
'45021' => '字段超过长度限制,请参考相应接口的字段说明。',
'40056' => '不合法的Code码。',
'43009' => '自定义SN权限,请前往公众平台申请。',
'43010' => '无储值权限,请前往公众平台申请。',
'40001' => '获取access_token时AppSecret错误',
'40002' => '不合法的凭证类型',
'40003' => '不合法的OpenID',
'40004' => '不合法的媒体文件类型',
'40005' => '不合法的文件类型',
'40006' => '不合法的文件大小',
'40007' => '不合法的媒体文件id',
'40008' => '不合法的消息类型',
'40009' => '不合法的图片文件大小',
'40010' => '不合法的语音文件大小',
'40011' => '不合法的视频文件大小',
'40012' => '不合法的缩略图文件大小',
'40013' => '不合法的AppID',
'40014' => '不合法的access_token',
'40015' => '不合法的菜单类型',
'40016' => '不合法的按钮个数',
'40017' => '不合法的按钮个数',
'40018' => '不合法的按钮名字长度',
'40019' => '不合法的按钮KEY长度',
'40020' => '不合法的按钮URL长度',
'40021' => '不合法的菜单版本号',
'40022' => '不合法的子菜单级数',
'40023' => '不合法的子菜单按钮个数',
'40024' => '不合法的子菜单按钮类型',
'40025' => '不合法的子菜单按钮名字长度',
'40026' => '不合法的子菜单按钮KEY长度',
'40027' => '不合法的子菜单按钮URL长度',
'40028' => '不合法的自定义菜单使用用户',
'40029' => '不合法的oauth_code',
'40030' => '不合法的refresh_token',
'40031' => '不合法的openid列表',
'40032' => '不合法的openid列表长度',
'40033' => '不合法的请求字符,不能包含\uxxxx格式的字符',
'40035' => '不合法的参数',
'40038' => '不合法的请求格式',
'40039' => '不合法的URL长度',
'40050' => '不合法的分组id',
'40051' => '分组名字不合法',
'40097' => '参数不正确,请参考字段要求检查json 字段',
'65104' => '门店的类型不合法,必须严格按照附表的分类填写',
'65105' => '图片url 不合法,必须使用接口1 的图片上传接口所获取的url',
'65106' => '门店状态必须未审核通过',
'65107' => '扩展字段为不允许修改的状态',
'65109' => '门店名为空',
'65110' => '门店所在详细街道地址为空',
'65111' => '门店的电话为空',
'65112' => '门店所在的城市为空',
'65113' => '门店所在的省份为空',
'65114' => '图片列表为空',
'65115' => 'poi_id 不正确',
'40117' => '分组名字不合法',
'40118' => 'media_id大小不合法',
'40119' => 'button类型错误',
'40120' => 'button类型错误',
'40121' => '不合法的media_id类型',
'40132' => '微信号不合法',
'40137' => '不支持的图片格式',
'40155' => '请勿添加其他公众号的主页链接',
'41001' => '缺少access_token参数',
'41002' => '缺少appid参数',
'41003' => '缺少refresh_token参数',
'41004' => '缺少secret参数',
'41005' => '缺少多媒体文件数据',
'41006' => '缺少media_id参数',
'41007' => '缺少子菜单数据',
'41008' => '缺少oauth code',
'41009' => '缺少openid',
'42001' => 'access_token超时',
'42002' => 'refresh_token超时',
'42003' => 'oauth_code超时',
'42007' => '用户需要重新授权',
'43001' => '需要GET请求',
'43002' => '需要POST请求',
'43003' => '需要HTTPS请求',
'43004' => '需要接收者关注',
'43005' => '需要好友关系',
'43019' => '需要将接收者从黑名单中移除',
'44001' => '多媒体文件为空',
'44002' => 'POST的数据包为空',
'44003' => '图文消息内容为空',
'44004' => '文本消息内容为空',
'45001' => '多媒体文件大小超过限制',
'45002' => '消息内容超过限制',
'45003' => '标题字段超过限制',
'45004' => '描述字段超过限制',
'45005' => '链接字段超过限制',
'45006' => '图片链接字段超过限制',
'45007' => '语音播放时间超过限制',
'45008' => '图文消息超过限制',
'45009' => '接口调用超过限制',
'45010' => '创建菜单个数超过限制',
'45011' => 'API调用太频繁,请稍候再试',
'45015' => '回复时间超过限制',
'45016' => '系统分组,不允许修改',
'45017' => '分组名字过长',
'45018' => '分组数量超过上限',
'45047' => '客服接口下行条数超过上限',
'46001' => '不存在媒体数据',
'46002' => '不存在的菜单版本',
'46003' => '不存在的菜单数据',
'46004' => '不存在的用户',
'47001' => '解析JSON/XML内容错误',
'48001' => 'api功能未授权',
'48002' => '粉丝拒收消息',
'48004' => 'api接口被封禁,请登录mp.weixin.qq.com查看详情',
'48005' => 'api禁止删除被自动回复和自定义菜单引用的素材',
'48006' => 'api禁止清零调用次数,因为清零次数达到上限',
'50001' => '用户未授权该api',
'50002' => '用户受限,可能是违规后接口被封禁',
'61451' => '参数错误(invalid parameter)',
'61452' => '无效客服账号(invalid kf_account)',
'61453' => '客服帐号已存在(kf_account exsited)',
'61454' => '客服帐号名长度超过限制(仅允许10个英文字符,不包括@及@后的公众号的微信号)',
'61455' => '客服帐号名包含非法字符(仅允许英文+数字)',
'61456' => '客服帐号个数超过限制(10个客服账号)',
'61457' => '无效头像文件类型',
'61450' => '系统错误',
'61500' => '日期格式错误',
'65301' => '不存在此menuid对应的个性化菜单',
'65302' => '没有相应的用户',
'65303' => '没有默认菜单,不能创建个性化菜单',
'65304' => 'MatchRule信息为空',
'65305' => '个性化菜单数量受限',
'65306' => '不支持个性化菜单的帐号',
'65307' => '个性化菜单信息为空',
'65308' => '包含没有响应类型的button',
'65309' => '个性化菜单开关处于关闭状态',
'65310' => '填写了省份或城市信息,国家信息不能为空',
'65311' => '填写了城市信息,省份信息不能为空',
'65312' => '不合法的国家信息',
'65313' => '不合法的省份信息',
'65314' => '不合法的城市信息',
'65316' => '该公众号的菜单设置了过多的域名外跳(最多跳转到3个域名的链接)',
'65317' => '不合法的URL',
'9001001' => 'POST数据参数不合法',
'9001002' => '远端服务不可用',
'9001003' => 'Ticket不合法',
'9001004' => '获取摇周边用户信息失败',
'9001005' => '获取商户信息失败',
'9001006' => '获取OpenID失败',
'9001007' => '上传文件缺失',
'9001008' => '上传素材的文件类型不合法',
'9001009' => '上传素材的文件尺寸不合法',
'9001010' => '上传失败',
'9001020' => '帐号不合法',
'9001021' => '已有设备激活率低于50%,不能新增设备',
'9001022' => '设备申请数不合法,必须为大于0的数字',
'9001023' => '已存在审核中的设备ID申请',
'9001024' => '一次查询设备ID数量不能超过50',
'9001025' => '设备ID不合法',
'9001026' => '页面ID不合法',
'9001027' => '页面参数不合法',
'9001028' => '一次删除页面ID数量不能超过10',
'9001029' => '页面已应用在设备中,请先解除应用关系再删除',
'9001030' => '一次查询页面ID数量不能超过50',
'9001031' => '时间区间不合法',
'9001032' => '保存设备与页面的绑定关系参数错误',
'9001033' => '门店ID不合法',
'9001034' => '设备备注信息过长',
'9001035' => '设备申请参数不合法',
'9001036' => '查询起始值begin不合法',

Yii2 定时任务创建(Console 任务)

Yii2的定时任务可以有两种写法,原理都是通过服务器的定时任务去调用

1.通过调用指定的URL访问 就相当于在浏览器中访问

2.通过console调用

下面我们就来说说Console 是如何实现定时任务的

一、首先在创建Controller 并继承 yii\console\Controller;

 

二、测试是否成功

三、设置定时任务

linux下,运行crontab -e

上面的例子表示每晚的21:30执行上面的定时程序

 

下面是定时任务设置的一些基本介绍

基本格式 :
*  *  *  *  *  command
分 时 日 月 周 命令

第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令

crontab文件的一些例子:

使用 gitosis 管理 git 服务器

通过apt安装,gitosis使用SSH key来认证用户,但用户不需要在主机上添加账号,而是使用服务器上的一个受限账号。 安装的过程需要在客户端和服务器之间切换,留意操作步骤之前的说明。这里服务器和客户端都是使用ubuntu linux。

服务器端(ip:192.168.1.254)
1. 安装 git
sudo apt-get install git-core

2. 安装  python 和 python-setuptools
sudo apt-get install python python-setuptools

3. 安装gitosis

cd /tmp
sudo git clone https://github.com/tv42/gitosis.git
cd gitosis
sudo python setup.py install

PS:git://eagain.net/gitosis 已经失效了,找了好久才有一个新的。

4. 创建git用户

sudo adduser
–system
–shell /bin/sh
–gecos ‘git user’
–group
–disabled-password
–home /home/git
git

客户端(也需要先安装 git)
5. 在 gitosis 管理员的机器上生成 密钥,把公钥重命名为comet@3GCOMET.pub,这里用scp传到服务器上
ssh-keygen -t rsa
mv id_rsa.pub comet@3GCOMET.pub
scp comet@3GCOMET.pub comet@192.168.1.254:comet@3GCOMET.pub

6.在 ~/.ssh/config 添加以下内容,以便连接到服务器
Host 192.168.1.254
Compression yes
IdentityFile ~/.ssh/id_rsa

服务器端
7.使用上面的 comet@3GCOMET.pub 初始化 gitosis
sudo -H -u git gitosis-init < comet@3GCOMET.pub
sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update

客户端
8.获取服务器上的 gitosis-admin 项目,会有keydir 文件夹和gitosis.conf
git clone git@192.168.1.254:gitosis-admin.git

9.添加新组jichuteam、用户comet@HP、项目jichu,并推送到远程服务器

注:如果客户端是windows,使用Puttygen生成公钥和私钥:参数为SSH-2 RSA,1024位,按需加上密码。

如果之前是使用ssh-keygen生成的,在这里直接Load private key,然后save private key,保存为ppk格式才能用。

复制puttygen显示的公钥保存为*.pub文件,注意不是”save public key”,保证公钥文件只有1行内容,否则不正确。把公钥给git的管理员,让他用gitosis-admin之类的方法把公钥加入git服务器,并设置好对应项目的权限。

在新的客户端生成密钥,并把公钥放到 gitosis-adminkeydir ,这里是comet@HP.pub
cd gitosis-admin
vi gitosis.conf

修改为下面内容,其中[gitosis]可以看gitosis/example.conf的说明,members 的 comet@HP 就是 comet@HP.pub 的文件名,多个用户用空格隔开
[gitosis]
gitweb = no
daemon = no
loglevel = DEBUG

 

[group gitosis-admin]
writable = gitosis-admin
members = comet@3GCOMET

[group jichuteam]
members = comet@HP
writable = jichu

git push

10.到其他地方建立项目根目录,并设置默认用户和邮箱,在.git/config添加远程服务器URL
mkdir jichu
cd jichu
git init
git config user.name Comet
git config user.email iamcomet@3gcomet.com
git remote add origin git@192.168.1.254:jichu.git

11.在 jichu 目录下进行开发,这里新建了 log.txt(一定要有新文件),提交到index,加上”initial import”信息并提交到本地仓库,最后是推送到远程服务器。
echo “begin develop” > log.txt
git add .
git commit -a -m “initial import”
git push origin master

服务器端
12.在服务器的 /home/git/repositories/ 可以看到有 jichu.git 的版本库。

linux常用svn命令

yum install subversion

安装完成之后, 你可以通过以下命令查看是svnversion版本信息:

svn –version

1、将文件checkout到本地目录
svn checkout path(path是服务器上的目录)
例如:svn checkout svn://192.168.1.1/pro/domain
简写:svn co
2、往版本库中添加新的文件
svn add file
例如:svn addtest.php(添加test.php)
svn add *.php(添加当前目录下所有的php文件)

你不能直接使用 svn add * 命令,必须使用 “svn add * –force” 命令。
请放心,–force参数没有看上去的那么可怕,svn会自动判断,看这个文件是否值得添加,–force参数只不过是驱使 svn 去检查一个子目录,而不管这个子目录是否已经纳入管理
3、将改动的文件提交到版本库
svn commit -m “LogMessage“ [-N] [–no-unlock] PATH(如果选择了保持锁,就使用–no-unlock开关)
例如:svn commit -m “add test file for my test“ test.php
简写:svn ci
4、加锁/解锁
svn lock -m “LockMessage“ [–force] PATH
例如:svn lock -m “lock test file“ test.php
svn unlock PATH
5、更新到某个版本
svn update -r m path
例如:
svn update如果后面没有目录,默认将当前目录以及子目录下的所有文件都更新到最新版本。
svn update -r 200 test.php(将版本库中的文件test.php还原到版本200)
svn update test.php(更新,于版本库同步。如果在提交的时候提示过期的话,是因为冲突,需要先update,修改文件,然后清除svn resolved,最后再提交commit)
简写:svn up
6、查看文件或者目录状态
1)svn status path(目录下的文件和子目录的状态,正常状态不显示)
【?:不在svn的控制中;M:内容被修改;C:发生冲突;A:预定加入到版本库;K:被锁定】
2)svn status -v path(显示文件和子目录状态)
第一列保持相同,第二列显示工作版本号,第三和第四列显示最后一次修改的版本号和修改人。
注:svn status、svn diff和 svn revert这三条命令在没有网络的情况下也可以执行的,原因是svn在本地的.svn中保留了本地版本的原始拷贝。
简写:svn st
7、删除文件
svn delete path -m “delete test fle“
例如:svn delete svn://192.168.1.1/pro/domain/test.php -m “delete test file”
或者直接svn delete test.php 然后再svn ci -m ‘delete test file‘,推荐使用这种
简写:svn (del, remove, rm)
8、查看日志
svn log path
例如:svn log test.php 显示这个文件的所有修改记录,及其版本号的变化
9、查看文件详细信息
svn info path
例如:svn info test.php
10、比较差异
svn diff path(将修改的文件与基础版本比较)
例如:svn diff test.php
svn diff -r m:n path(对版本m和版本n比较差异)
例如:svn diff -r 200:201 test.php
简写:svn di
11、将两个版本之间的差异合并到当前文件
svn merge -r m:n path
例如:svn merge -r 200:205 test.php(将版本200与205之间的差异合并到当前文件,但是一般都会产生冲突,需要处理一下)
12、SVN 帮助
svn help
svn help ci
——————————————————————————
以上是常用命令,下面写几个不经常用的
——————————————————————————
13、版本库下的文件和目录列表
svn list path
显示path目录下的所有属于版本库的文件和目录
简写:svn ls
14、创建纳入版本控制下的新目录
svn mkdir: 创建纳入版本控制下的新目录。
用法:
1、mkdir PATH…
2、mkdir URL…
创建版本控制的目录。
1、每一个以工作副本 PATH 指定的目录,都会创建在本地端,并且加入新增调度,以待下一次的提交。
2、每个以URL指定的目录,都会透过立即提交于仓库中创建。在这两个情况下,所有的中间目录都必须事先存在。
15、恢复本地修改

svn revert: 恢复原始未改变的工作副本文件 (恢复大部份的本地修改)。revert:
用法: revert PATH…
注意: 本子命令不会存取网络,并且会解除冲突的状况。但是它不会恢复被删除的目录
16、代码库URL变更
svn switch (sw): 更新工作副本至不同的URL。
用法: 1、switch URL [PATH]
2、switch –relocate FROM TO [PATH…]
1、更新你的工作副本,映射到一个新的URL,其行为跟“svn update”很像,也会将服务器上文件与本地文件合并。这是将工作副本对应到同一仓库中某个分支或者标记的方法。
2、改写工作副本的URL元数据,以反映单纯的URL上的改变。当仓库的根URL变动(比如方案名或是主机名称变动),但是工作副本仍旧对映到同一仓库的同一目录时使用这个命令更新工作副本与仓库的对应关系。
17、解决冲突
svn resolved: 移除工作副本的目录或文件的“冲突”状态。
用法: resolved PATH…
注意: 本子命令不会依语法来解决冲突或是移除冲突标记;它只是移除冲突的
相关文件,然后让 PATH 可以再次提交。
18、输出指定文件或URL的内容。
svn cat 目标[@版本]…如果指定了版本,将从指定的版本开始查找。
svn cat -r PREV filename > filename (PREV 是上一版本,也可以写具体版本号,这样输出结果是可以提交的)

随机数的生成函数,这里贡献给大家。

首先是要用mt_rand()函数生成指定个数的随机数字;

然后使用array_unique()函数去重;

因为去重了;所以得到的数字就不够指定个数了;

所以;核心是要用while循环;直到得到指定个数的数字;

到这里基本可以是结束了;

对于追求完美的人来说;还可以再用个sort();

目的不是要用来排序;主要是将得到的数组key格式化;

用代码来说话;就如下;

<?php
/**
* 生成不重复的随机数
* @param  int $start  需要生成的数字开始范围
* @param  int $end    结束范围
* @param  int $length 需要生成的随机数个数
* @return array       生成的随机数
*/
function get_rand_number($start=1,$end=10,$length=4){
$connt=0;
$temp=array();
while($connt<$length){
$temp[]=mt_rand($start,$end);
$data=array_unique($temp);
$connt=count($data);
}
sort($data);
return $data;
}

当然;重点不是这个函数;重点是这个函数的思路;可以解决很多类似的问题;

6f8cd40d-4516-4c6d-b602-fb8671ab5530

作为PHP开发者请务必了解Composer

Composer是一个非常流行的PHP包依赖管理工具,已经取代PEAR包管理器,对于PHP开发者来说掌握Composer是必须的.

对于使用者来说Composer非常的简单,通过简单的一条命令将需要的代码包下载到vendor目录下,然后开发者就可以引入包并使用了.

其中的关键在于你项目定义的composer.json,可以定义项目需要依赖的包(可能有多个),而依赖的包可能又依赖其他的包(这就是组件的好处),这些都不用你烦心,Composer会自动下载你需要的一切,一切在于composer.json的定义.

Composer对于使用者来说是很透明,但是其背后的理念还是需要了解一下的,其的诞生也不是偶然的,得益于Github的快速发展,PHP语言也越来越现代化,显得更高大上了.

为了理解Composer,先大概了解下其结构:

Composer的结构

  • Composer命令行工具:

    这个理解就比较简单了,通过使用者定义的Composer.json去下载你需要的代码,假如只是简单的使用Composer,那么掌握一些具体命令就完全可以了

  • Autoloading代码加载器:

    通过Composer,开发者可以通过多种方式去使用,而其中的关键在于PHP的命名空间概念,以及PSR-4标准的发展,Composer只是根据这二者开发了一个代码自动加载器

  • Github:

    有了Github,PHP开发人员可以将开源的代码托管在这上面,而Composer的发展源于Github,Composer本质上就是将Github上的代码下载到本地.

  • Packagist:

    对于使用者来说使用的是Composer的命令行工具,那么命令行工具怎么知道有多少包可以被用户使用呢,这主要就是依赖于Packagist,Packagist是Composer主要的一个包信息存储库,包开发者将具体代码托管到Github上,将包信息提交到Packagist上,这样使用者就可以通过Composer去使用.

  • Composer根据本地定义的composer.json信息去查询Packagist,Packagist根据Composer.json/Package.json信息解析,最终对应到github仓库,Composer最终下载代码的时候还要依赖于Github仓库上的Composer.json,这里涉及到三种类型的composer.json,含义是不一样的.
  • Composer.json:

    这是Composer的核心,是Composer的规则,上面也提到了三种类型的Composer.json,在使用的时候一定要注意区分,我初学的时候就总是搞乱.

Composer命令行工具

composer init

使用者可以在自己的项目下创建composer.json以便定义你项目的依赖包,也可以通过composer init交互式的创建composer.json.

composer install

应该是最常用的命令,composer会根据本地的composer.json安装包,将下载的包放入项目下的vendor目录下,同时将安装时候的包版本信息放入到composer.lock,以便锁定版本.

其实在install的时候,假如发现composer.lock版本和目前vendor目录下的代码版本是一致的,则Composer会什么也不做,composer.lock的目的就是让你安心在目前这个版本下工作,而不获取最新版本的包.

composer update

那么如何更新composer.lock以便获取到最新版本的包呢?通过这个命令即可更新最新版本的包

composer config

这个命令还是建议了解下,全局的配置保存在COMPOSER_HOME/config.json,非全局的配置信息则存储在本项目目录下.

composer configlistg

composer configg notifyoninstall false

composer global config bindirabsolute

composer create-project

这个命令不常用,但是个人觉得还是很重要的,使用普通的install命令是将项目所有的依赖包下载到本项目vendor目录下.而通过这个命令则是将所有的代码及其依赖的包放到一个目录下,相当于执行了一个git clone命令,一般是包的开发者可能为了修复bug会使用该命令.

composer global

这是一个全局的安装命令,它允许你在COMPOSER_HOME目录下执行Composer的命令,比如install,update.当然你的COMPOSER_HOME要在$PATH环境下.

比如执行composer global require fabpot/php-cs-fixer,现在php-cs-fixer命令行可以全局运行了,如果稍后想更新它,只需要运行composer global update

composer dump-autoload

当你修改项目下的composer.json的文件,并不一定要运行composer update命令进行更新,有的时候可以使用该命令来更新加载器,比如你要引用本地自定义的包(不是来自于packagist),后面会通过实践来说明该命令.

composer require

假如手动或者交互式创建composer.json文件,可以直接使用该命令来安装包

composer require  cerdic/csstidy:1.5.2

composer require “ywdblog/phpcomposer:dev-master”

–prefer-source和–prefer-dist参数

–prefer-dist:对于稳定的包来说,一般Composer安装默认使用该参数,这也能加快安装,比如有可能直接从packagist安装了相应的包,而不用实际去Github上下载包.

–prefer-source:假如使用该参数,则会直接从Github上安装,安装包后vendor目录下还含有.git信息

composer require “ywdblog/phpcomposer:dev-master”prefersource

#在vendor/ywdblog/phpcomposer目录下含有.git信息

如何给Composer添加代理

在国内使用Composer下载特别慢,可以通过二个方法进行加速

  • composer config repo.packagist composer “https://packagist.phpcomposer.com“
  • 编辑composer.json

“repositories”: {

  “packagist”: {

      “type”: “composer”,

      “url”: “https://packagist.phpcomposer.com”

  }

}

Autoloading代码加载器

composer本身集成一个autoloader,支持PSR-4,PSR-0,classmap,files autoloading.

这里通过一个例子来说明通过Composer如何引用classmap,files,本地符合PSR-4标准的代码

编辑composer.json

“autoload”: {

  “classmap”: [“othsrc/”,“classsrc.php”],

  “files”: [“othsrc/filesrc.php”],

  “psr-4”: {“Foo\Bar\”: “src}

}

composer dump-autoload

通过上述的操作,对于PSR-4来说等同注册了一个PSR-4 autoloader(从FooBar命名空间)

假如不想使用Composer的autoloader,可以直接包含vendor/composer/autoload_*.php 文件,配置自己的加载器.

具体的例子托管在github上,可参考.

Repositories

关于Repositories,了解其不是必须的,但是假如掌握则更能理解Composer,对于Repositories,其中文文档和英文文档解释的很好,这里也进行了一些摘抄.

基本概念

包:

Composer是一个依赖管理工具,它在本地安装一些资源包和包的描述(比如包名称和对应的版本),比较重要的元数据描述是dist和source,dist指向一个存档,该存档是对一个资源包的某个版本的数据进行的打包.source指向一个开发中的源,这通常是一个源代码仓库(比如git)

资源库:

一个资源库是一个包的来源.它是一个packages/versions的列表.

Composer将查看所有你定义的repositories以找到项目需要的资源包(这句话很重要).

默认情况下已经将Packagist.org注册到Composer(或者理解为Packagist.org是Composer资源库默认的仓库类型)

Composer资源库类型

Composer资源库包括四种类型,默认的是composer类型,也就是packagist.org所使用的资源类型.

它使用一个单一的packages.json文件,包含了所有的资源包元数据.当你将包发布到pckagist.org上,则默认系统会创建一个packages.json,不过我没有找到我的包对应的文件.

VCS资源库类型

假如你想构建一个私有的Composer私有资源库类型,可以使用该类型,这里举一个例子,比如你在自己项目的composer.json定义如下,则就可以使用对应的Github上的代码了.

{

    “repositories”: [

    {

        “type”: “vcs”,

        “url”: “https://github.com/ywdblog/phpcomposer”

    }

    ],

    “require”: {

        “ywdblog/phpcomposer”: “dev-master”

    }

}

当运行composer update的时候,Comoser实际上是从Github上下载包而不是从pckagist.org上下载.

另外假如需要使用Package资源库类型或者PEAR资源库类型,参考官方文档即可,一般在composer.json中定义name、version属性即可.

Composer.json

在本文上面也多次提到了composer.json,比如你希望使用第三方包则需要在本地定义composer.json,Composer安装第三方包后,也会在第三方包目录下发现composer.json,那么这二者都叫composer.json,有什么区别呢?理解这非常的重要.

假如你在自己的项目下面定义一个composer.json,则这个包称之为ROOT包,这个composer.json定义你项目需要的条件(比如你的项目可能依赖一个第三方包).

composer.json中有些属性只能被ROOT包使用,比如config属性只在ROOT包中生效.

一个资源包是不是ROOT包,取决于它的上下文,比如你git clone ywdblog/phpcomposer,则这时候本地phpcomposer目录就是ROOT包,假如你在本地phpcomposer目录下composer require ywdblog/phpcomposer,则这时候你的项目phpcomposer就是ROOT包.

了解composer-schema.json可参考该网址,Laravel作为一个成熟的框架,其定义的composer.json非常经典

关于包的版本

当使用者在本地配置composer.json的时候,可以指定需要包的特定版本,Composer支持从Github仓库中下载Tag或者分支下的包.

对于Github上的Tag来说,Packagist会创建对应包的版本,它符合X.Y.Z,vX.Y.Z,X.Y.Z-包类型,就是说Github上虽然只有一个特定版本的包,但Composer支持多种形式的引用方式,比如:

composer require monolog/monolog  1.0.0RC1

composer require monolog/monolog  v1.0.0RC1

composer require monolog/monolog  1.0.*

composer require monolog/monolog  ~1.10

对于Github上的分支来说,Packagist会创建对应包的版本,假如分支名看起来像一个版本,将创建{分支名}-dev的包版本号,如果分支名看起来不像一个版本号,它将会创建dev-{分支名}形式的版本号

composer require monolog/monolog  masterdev

composer require monolog/monolog  master.xdev

总结:

理解Composer,最重要的是实践,最后也能明白PSR-4和命名空间,也可以尝试将你的项目发布到pckagist.org上.

搭建Git服务器

在远程仓库一节中,我们讲了远程仓库实际上和本地仓库没啥不同,纯粹为了7×24小时开机并交换大家的修改。

GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓库使用。

搭建Git服务器需要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt命令就可以完成安装。

假设你已经有sudo权限的用户账号,下面,正式开始安装。

第一步,安装git

$ sudo apt-get install git

第二步,创建一个git用户,用来运行git服务:

$ sudo adduser git

第三步,创建证书登录:

收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。

第四步,初始化Git仓库:

先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:

$ sudo git init --bare sample.git

Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git

$ sudo chown -R git:git sample.git

第五步,禁用shell登录:

出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:

git:x:1001:1001:,,,:/home/git:/bin/bash

改为:

git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell

这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。

第六步,克隆远程仓库:

现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:

$ git clone git@server:/srv/sample.git
Cloning into 'sample'...
warning: You appear to have cloned an empty repository.

剩下的推送就简单了。

管理公钥

如果团队很小,把每个人的公钥收集起来放到服务器的/home/git/.ssh/authorized_keys文件里就是可行的。如果团队有几百号人,就没法这么玩了,这时,可以用Gitosis来管理公钥。

这里我们不介绍怎么玩Gitosis了,几百号人的团队基本都在500强了,相信找个高水平的Linux管理员问题不大。

管理权限

有很多不但视源代码如生命,而且视员工为窃贼的公司,会在版本控制系统里设置一套完善的权限控制,每个人是否有读写权限会精确到每个分支甚至每个目录下。因为Git是为Linux源代码托管而开发的,所以Git也继承了开源社区的精神,不支持权限控制。不过,因为Git支持钩子(hook),所以,可以在服务器端编写一系列脚本来控制提交等操作,达到权限控制的目的。Gitolite就是这个工具。

这里我们也不介绍Gitolite了,不要把有限的生命浪费到权限斗争中。

小结

  • 搭建Git服务器非常简单,通常10分钟即可完成;
  • 要方便管理公钥,用Gitosis;
  • 要像SVN那样变态地控制权限,用Gitolite。

Vsftp的安装,Vsftp添加用户linux/windows

关于Vsftp的安装以及配置方法现总结如下(包括vsftp如何添加用户)不多说,直接看操作流程:

设置方法:

aliyun Linux(Redhat)安装vsftp软件

1.更新yum源

首先需要更新系统的yum源,便捷工具下载地址:update_source.zip。这里需要注意的是,目前文件无法传输,所以想要运行 update_source.sh 只能用文本打开,复制粘贴到阿里云服务器系统运行。

2.安装vsftp

使用yum命令安装vsftp

#yum install vsftpd -y

3.添加ftp帐号和目录

先检查一下nologin的位置,通常在/usr/sbin/nologin或者/sbin/nologin下。

使用下面的命令创建帐户,该命令指定了/ftp为用户test的家目录,您可以自己定义帐户名和目录:

#useradd -d /ftp -s /sbin/nologin test

修改该帐户密码:

#passwd test

修改指定目录的权限

#chown -R test:test /ftp

4.配置vsftp

编辑vsftp配置文件,命令如下:

#vi /etc/vsftpd/vsftpd.conf

将配置文件中”anonymous_enable=YES “改为 “anonymous_enable=NO”

取消如下配置前的注释符号:

#local_enable=YES

#write_enable=YES

#chroot_local_user=YES

#ascii_upload_enable 允许使用ascii码上传

#ascii_download_enable 允许使用ascii码下载

保存修改,按ESC键,输入:wq

5.修改shell配置

vi编辑/etc/shells,如果该文件里没有/usr/sbin/nologin或者/sbin/nologin(具体看当前系统配置)则追加进去

6.启动vsftp服务并测试登录

使用命令启动vsftp服务:

#service vsftpd start

然后用帐号test测试下是否可以登陆ftp。目录是/ftp  推荐用filezilla比较流行的ftp工具。

dedecms后台删除不了文章,文章删除之后,提示成功,但是实际未删除_dedecms

前些日子给一朋友用dedecms套用了一个站点,因为都是用的模板,套起来非常快,三两小时就搞定,搞完之后马上交稿。好景不长,没过多久,这朋友找上门来说:dedecms后台删除不了文章,文章删除之后,提示成功,但是实际后台未删除。

后来我给检查了一番,因为对dedecms这种cms,一些问题基本都是站长摸透了的,这类问题应该可以说是家常便饭吧。于是baidu,google了一下,寥寥无几的答案,大都是无关紧要的答案,亦或是答非所问,也许都是抱着灌水的态度把,却而止步。

决定对程序进行排查了,得得看看删除程序是怎么进行的吧,查了几个php页面:archives_do.php

QQ图片20160708151305

发现这里用了的函数  DelArc

然后继续往下找到这个函数,函数来自inc_batchup.php文件

QQ截图20160708151534

 

看到这里就基本一目了然了,将sql进行执行查询出来,发现这里表里面的数据让人大吃一惊。

将表中的数据进行校对处理,最终得以解决了。

将在这篇文章里面整理linux之常用命令

  • cd命令

这是一个非常基本,也是大家经常需要使用的命令,它用于切换当前目录,它的参数是要切换到的目录的路径,可以是绝对路径,也可以是相对路径。如:
cd /root/Docements # 切换到目录/root/Docements
cd ./path          # 切换到当前目录下的path目录中,“.”表示当前目录  
cd ../path         # 切换到上层目录中的path目录中,“..”表示上一层目录
  • ls命令

这是一个非常有用的查看文件与目录的命令,list之意,它的参数非常多,下面就列出一些我常用的参数吧,如下:
-l :列出长数据串,包含文件的属性与权限数据等
-a :列出全部的文件,连同隐藏文件(开头为.的文件)一起列出来(常用)
-d :仅列出目录本身,而不是列出目录的文件数据
-h :将文件容量以较易读的方式(GB,kB等)列出来
-R :连同子目录的内容一起列出(递归列出),等于该目录下的所有文件都会显示出来
注:这些参数也可以组合使用,下面举两个例子:
ls -l #以长数据串的形式列出当前目录下的数据文件和目录
ls -lR #以长数据串的形式列出当前目录下的所有文件
  • grep命令

该命令常用于分析一行的信息,若当中有我们所需要的信息,就将该行显示出来,该命令通常与管道命令一起使用,用于对一些命令的输出进行筛选加工等等,它的简单语法为
grep [-acinv] [--color=auto] '查找字符串' filename
它的常用参数如下:
-a :将binary文件以text文件的方式查找数据
-c :计算找到‘查找字符串’的次数
-i :忽略大小写的区别,即把大小写视为相同
-v :反向选择,即显示出没有‘查找字符串’内容的那一行
# 例如:
# 取出文件/etc/man.config中包含MANPATH的行,并把找到的关键字加上颜色
grep --color=auto 'MANPATH' /etc/man.config
# 把ls -l的输出中包含字母file(不区分大小写)的内容输出
ls -l | grep -i file
  • find命令

find是一个基于查找的功能非常强大的命令,相对而言,它的使用也相对较为复杂,参数也比较多,所以在这里将给把它们分类列出,它的基本语法如下:
find [PATH] [option] [action]

# 与时间有关的参数:
-mtime n : n为数字,意思为在n天之前的“一天内”被更改过的文件;
-mtime +n : 列出在n天之前(不含n天本身)被更改过的文件名;
-mtime -n : 列出在n天之内(含n天本身)被更改过的文件名;
-newer file : 列出比file还要新的文件名
# 例如:
find /root -mtime 0 # 在当前目录下查找今天之内有改动的文件

# 与用户或用户组名有关的参数:
-user name : 列出文件所有者为name的文件
-group name : 列出文件所属用户组为name的文件
-uid n : 列出文件所有者为用户ID为n的文件
-gid n : 列出文件所属用户组为用户组ID为n的文件
# 例如:
find /home/ljianhui -user ljianhui # 在目录/home/ljianhui中找出所有者为ljianhui的文件

# 与文件权限及名称有关的参数:
-name filename :找出文件名为filename的文件
-size [+-]SIZE :找出比SIZE还要大(+)或小(-)的文件
-tpye TYPE :查找文件的类型为TYPE的文件,TYPE的值主要有:一般文件(f)、设备文件(b、c)、
             目录(d)、连接文件(l)、socket(s)、FIFO管道文件(p);
-perm mode :查找文件权限刚好等于mode的文件,mode用数字表示,如0755;
-perm -mode :查找文件权限必须要全部包括mode权限的文件,mode用数字表示
-perm +mode :查找文件权限包含任一mode的权限的文件,mode用数字表示
# 例如:
find / -name passwd # 查找文件名为passwd的文件
find . -perm 0755 # 查找当前目录中文件权限的0755的文件
find . -size +12k # 查找当前目录中大于12KB的文件,注意c表示byte
  • cp命令

该命令用于复制文件,copy之意,它还可以把多个文件一次性地复制到一个目录下,它的常用参数如下:
-a :将文件的特性一起复制
-p :连同文件的属性一起复制,而非使用默认方式,与-a相似,常用于备份
-i :若目标文件已经存在时,在覆盖时会先询问操作的进行
-r :递归持续复制,用于目录的复制行为
-u :目标文件与源文件有差异时才会复制
例如 :
cp -a file1 file2 #连同文件的所有特性把文件file1复制成文件file2
cp file1 file2 file3 dir #把文件file1、file2、file3复制到目录dir中
6、mv命令
该命令用于移动文件、目录或更名,move之意,它的常用参数如下:
-f :force强制的意思,如果目标文件已经存在,不会询问而直接覆盖
-i :若目标文件已经存在,就会询问是否覆盖
-u :若目标文件已经存在,且比目标文件新,才会更新
注:该命令可以把一个文件或多个文件一次移动一个文件夹中,但是最后一个目标文件一定要是“目录”。
例如:
mv file1 file2 file3 dir # 把文件file1、file2、file3移动到目录dir中
mv file1 file2 # 把文件file1重命名为file2
  • rm命令

该命令用于删除文件或目录,remove之间,它的常用参数如下:
-f :就是force的意思,忽略不存在的文件,不会出现警告消息
-i :互动模式,在删除前会询问用户是否操作
-r :递归删除,最常用于目录删除,它是一个非常危险的参数
例如:
rm -i file # 删除文件file,在删除之前会询问是否进行该操作
rm -fr dir # 强制删除目录dir中的所有文件
  • ps命令

该命令用于将某个时间点的进程运行情况选取下来并输出,process之意,它的常用参数如下:
-A :所有的进程均显示出来
-a :不与terminal有关的所有进程
-u :有效用户的相关进程
-x :一般与a参数一起使用,可列出较完整的信息
-l :较长,较详细地将PID的信息列出
其实我们只要记住ps一般使用的命令参数搭配即可,它们并不多,如下:
ps aux # 查看系统所有的进程数据
ps ax # 查看不与terminal有关的所有进程
ps -lA # 查看系统所有的进程数据
ps axjf # 查看连同一部分进程树状态
  • kill命令

该命令用于向某个工作(%jobnumber)或者是某个PID(数字)传送一个信号,它通常与ps和jobs命令一起使用,它的基本语法如下:
kill -signal PID
signal的常用参数如下:
注:最前面的数字为信号的代号,使用时可以用代号代替相应的信号。
1:SIGHUP,启动被终止的进程
2:SIGINT,相当于输入ctrl+c,中断一个程序的进行
9:SIGKILL,强制中断一个进程的进行
15:SIGTERM,以正常的结束进程方式来终止进程
17:SIGSTOP,相当于输入ctrl+z,暂停一个进程的进行
例如:
# 以正常的结束进程方式来终于第一个后台工作,可用jobs命令查看后台中的第一个工作进程
kill -SIGTERM %1 
# 重新改动进程ID为PID的进程,PID可用ps命令通过管道命令加上grep命令进行筛选获得
kill -SIGHUP PID
  • killall命令

该命令用于向一个命令启动的进程发送一个信号,它的一般语法如下:
killall [-iIe] [command name]
它的参数如下:
-i :交互式的意思,若需要删除时,会询问用户
-e :表示后面接的command name要一致,但command name不能超过15个字符
-I :命令名称忽略大小写
# 例如:
killall -SIGHUP syslogd # 重新启动syslogd
  • file命令

该命令用于判断接在file命令后的文件的基本数据,因为在Linux下文件的类型并不是以后缀为分的,所以这个命令对我们来说就很有用了,它的用法非常简单,基本语法如下:
file filename
#例如:
file ./test
  • tar命令

该命令用于对文件进行打包,默认情况并不会压缩,如果指定了相应的参数,它还会调用相应的压缩程序(如gzip和bzip等)进行压缩和解压。它的常用参数如下:
-c :新建打包文件
-t :查看打包文件的内容含有哪些文件名
-x :解打包或解压缩的功能,可以搭配-C(大写)指定解压的目录,注意-c,-t,-x不能同时出现在同一条命令中
-j :通过bzip2的支持进行压缩/解压缩
-z :通过gzip的支持进行压缩/解压缩
-v :在压缩/解压缩过程中,将正在处理的文件名显示出来
-f filename :filename为要处理的文件
-C dir :指定压缩/解压缩的目录dir
上面的解说可以已经让你晕过去了,但是通常我们只需要记住下面三条命令即可:
压缩:tar -jcv -f filename.tar.bz2 要被处理的文件或目录名称
查询:tar -jtv -f filename.tar.bz2
解压:tar -jxv -f filename.tar.bz2 -C 欲解压缩的目录
注:文件名并不定要以后缀tar.bz2结尾,这里主要是为了说明使用的压缩程序为bzip2
  • cat命令

该命令用于查看文本文件的内容,后接要查看的文件名,通常可用管道与more和less一起使用,从而可以一页页地查看数据。例如:
cat text | less # 查看text文件中的内容
# 注:这条命令也可以使用less text来代替
  • chgrp命令

该命令用于改变文件所属用户组,它的使用非常简单,它的基本用法如下:
chgrp [-R] dirname/filename
-R :进行递归的持续对所有文件和子目录更改
# 例如:
chgrp users -R ./dir # 递归地把dir目录下中的所有文件和子目录下所有文件的用户组修改为users
  • chown命令

该命令用于改变文件的所有者,与chgrp命令的使用方法相同,只是修改的文件属性不同,不再详述。
  • chmod命令

该命令用于改变文件的权限,一般的用法如下:
chmod [-R] xyz 文件或目录
-R:进行递归的持续更改,即连同子目录下的所有文件都会更改
同时,chmod还可以使用u(user)、g(group)、o(other)、a(all)和+(加入)、-(删除)、=(设置)跟rwx搭配来对文件的权限进行更改。
# 例如:
chmod 0755 file # 把file的文件权限改变为-rxwr-xr-x
chmod g+w file # 向file的文件权限中加入用户组可写权限
  • vim命令

该命令主要用于文本编辑,它接一个或多个文件名作为参数,如果文件存在就打开,如果文件不存在就以该文件名创建一个文件。vim是一个非常好用的文本编辑器,它里面有很多非常好用的命令,在这里不再多说。你可以从这里下载vim常用操作的详细说明。
  • gcc命令

对于一个用Linux开发C程序的人来说,这个命令就非常重要了,它用于把C语言的源程序文件,编译成可执行程序,由于g++的很多参数跟它非常相似,所以这里只介绍gcc的参数,它的常用参数如下:
-o :output之意,用于指定生成一个可执行文件的文件名
-c :用于把源文件生成目标文件(.o),并阻止编译器创建一个完整的程序
-I :增加编译时搜索头文件的路径
-L :增加编译时搜索静态连接库的路径
-S :把源文件生成汇编代码文件
-lm:表示标准库的目录中名为libm.a的函数库
-lpthread :连接NPTL实现的线程库
-std= :用于指定把使用的C语言的版本

# 例如:
# 把源文件test.c按照c99标准编译成可执行程序test
gcc -o test test.c -lm -std=c99
#把源文件test.c转换为相应的汇编程序源文件test.s
gcc -S test.c
  • time命令

该命令用于测算一个命令(即程序)的执行时间。它的使用非常简单,就像平时输入命令一样,不过在命令的前面加入一个time即可,例如:
time ./process
time ps aux
在程序或命令运行结束后,在最后输出了三个时间,它们分别是:
user:用户CPU时间,命令执行完成花费的用户CPU时间,即命令在用户态中执行时间总和;
system:系统CPU时间,命令执行完成花费的系统CPU时间,即命令在核心态中执行时间总和;
real:实际时间,从command命令行开始执行到运行终止的消逝时间;
  •  lsblk命令

lsblk“就是列出块设备。除了RAM外,以标准的树状输出格式,整齐地显示块设备。

lsblk -l”命令以列表格式显示块设备(而不是树状格式)。

  • md5sum命令

md5sum”就是计算和检验MD5信息签名。md5 checksum(通常叫做哈希)使用匹配或者验证文件的文件的完整性,因为文件可能因为传输错误,磁盘错误或者无恶意的干扰等原因而发生改变。

 

  • uname命令

uname“命令就是Unix Name的简写。显示机器名,操作系统和内核的详细信息。

root@raspberrypi:/# uname -a
Linux raspberrypi 3.6.11+ #528 PREEMPT Tue Aug 20 00:25:53 BST 2013 armv6l GNU/Linux
  • history命令

history”命令就是历史记录。它显示了在终端中所执行过的所有命令的历史。

注意:按住“CTRL + R”就可以搜索已经执行过的命令,它可以在你写命令时自动补全。

  • sudo命令

sudo”(super user do)命令允许授权用户执行超级用户或者其它用户的命令。通过在sudoers列表的安全策略来指定。

 

  •  mkdir命令

mkdir”(Make directory)命令在命名路径下创建新的目录。然而如果目录已经存在了,那么它就会返回一个错误信息”不能创建文件夹,文件夹已经存在了”(“cannot create folder, folder already exists”)

root@raspberrypi:/opt/labpark# mkdir raspbox

注意:目录只能在用户拥有写权限的目录下才能创建。mkdir:不能创建目录`tecmint`,因为文件已经存在了。(上面的输出中不要被文件迷惑了,你应该记住我开头所说的-在linux中,文件,文件夹,驱动,命令,脚本都视为文件)

  • touch 命令

touch”命令代表了将文件的访问和修改时间更新为当前时间。touch命令只会在文件不存在的时候才会创建它。如果文件已经存在了,它会更新时间戳,但是并不会改变文件的内容。

root@raspberrypi:/opt/labpark# touch rasp.txt

注意:touch 可以用来在用户拥有写权限的目录下创建不存在的文件。

  • apt命令

Debian系列以“apt”命令为基础,“apt”代表了Advanced Package Tool。APT是一个为Debian系列系统(Ubuntu,Kubuntu等等)开发的高级包管理器,在Gnu/Linux系统上,它会为包自动地,智能地搜索,安装,升级以及解决依赖。

  • pwd 命令

pwd”(print working directory),在终端中显示当前工作目录的全路径。

root@raspberrypi:/opt/labpark# pwd
/opt/labpark

  •  命令: Find

搜索指定目录下的文件,从开始于父目录,然后搜索子目录。

root@raspberrypi:/opt/labpark# find book*
book_backup.txt
book.txt

 

root@raspberrypi:/opt/labpark# find -name *.c
./hello.c

 

root@raspberrypi:/opt/labpark# find -iname FACE*
./facebook.txt

 

注意: `-name‘选项是搜索大小写敏感。可以使用`-iname‘选项,这样在搜索中可以忽略大小写。(*是通配符,可以搜索所有的文件;‘.sh‘你可以使用文件名或者文件名的一部分来制定输出结果)

 

  • 命令: grep

 

grep‘命令搜索指定文件中包含给定字符串或者单词的行。举例搜索‘/etc/passwd‘文件中的‘pi’

root@raspberrypi:/opt/labpark# grep pi /etc/passwd
pi:x:1000:1000:,,,:/opt/wwwroot:/bin/bash

使用’-i’选项将忽略大小写。

root@raspberrypi:/opt/labpark# grep -i  'PI' /etc/passwd
pi:x:1000:1000:,,,:/opt/wwwroot:/bin/bash

使用’-r’选项递归搜索所有自目录下包含字符串 “localhost“.的行。

root@raspberrypi:/opt/labpark# grep -r "localhost" /etc/php5/
/etc/php5/cgi/php.ini:SMTP = localhost
/etc/php5/cli/php.ini:SMTP = localhost
/etc/php5/fpm/php.ini:SMTP = localhost

注意:您还可以使用以下选项:

  1. -w 搜索单词 (egrep -w ‘word1|word2‘ /path/to/file).
  2. -c 用于统计满足要求的行 (i.e., total number of times the pattern matched) (grep -c ‘word‘ /path/to/file).
  3. –color 彩色输出 (grep –color server /etc/passwd).

 

  •  命令: man

man‘是系统帮助页。Man提供命令所有选项及用法的在线文档。几乎所有的命令都有它们的帮助页

  • 命令: ps

ps命令给出正在运行的某个进程的状态,每个进程有特定的id成为PID。

  • 命令: whereis

whereis的作用是用来定位命令的二进制文件\资源\或者帮助页.举例来说,获得ls和kill命令的二进制文件/资源以及帮助页

  • 命令: service

service‘命令控制服务的启动、停止和重启,它让你能够不重启整个系统就可以让配置生效以开启、停止或者重启某个服务。

  • 命令: alias

alias是一个系统自建的shell命令,允许你为名字比较长的或者经常使用的命令指定别名。

我经常用ls -l‘命令,它有五个字符(包括空格)。于是我为它创建了一个别名‘l’。

  • 命令: df

报告系统的磁盘使用情况。在跟踪磁盘使用情况方面对于普通用户和系统管理员都很有用。 ‘df‘ 通过检查目录大小工作,但这一数值仅当文件关闭时才得到更新。

  • 命令: du

估计文件的空间占用。 逐层统计文件(例如以递归方式)并输出摘要。

注意: ‘df‘ 只显示文件系统的使用统计,但‘du‘统计目录内容。

  • 命令: passwd

这是一个很重要的命令,在终端中用来改变自己密码很有用。显然的,因为安全的原因,你需要知道当前的密码。

root@raspberrypi:/opt/wwwroot# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

 

  • 命令: lpr

这个命令用来在命令行上将指定的文件在指定的打印机上打印。

root@raspberry:~# lpr -P deskjet-4620-series 1-final.pdf

 

注意: “lpq“命令让你查看打印机的状态(是开启状态还是关闭状态)和等待打印中的工作(文件)的状态。

 

  • 命令: cmp

比较两个任意类型的文件并将结果输出至标准输出。如果两个文件相同, ‘cmp‘默认返回0;如果不同,将显示不同的字节数和第一处不同的位置。

  • 命令: wget

Wget是用于非交互式(例如后台)下载文件的免费工具.支持HTTPHTTPSFTP协议和 HTTP 代理。

 

  • 命令: mount

mount 是一个很重要的命令,用来挂载不能自动挂载的文件系统。你需要root权限挂载设备。

在插入你的文件系统后,首先运行”lsblk“命令,识别出你的设备,然后把分配的设备名记下来。

  • 命令: ifconfig

ifconfig用来配置常驻内核的网络接口信息。在系统启动必要时用来设置网络适配器的信息。之后,它通常是只需要在调试时或当系统需要调整时使用。

  •  命令: netstat

netstat命令显示各种网络相关的信息,如网络连接,路由表,接口统计,伪装连接,组播成员身份等….

  • 命令: uptime

你连接到你的 Linux 服务器时发现一些不寻常或恶意的东西,你会做什么?猜测……不,绝不!你可以运行uptime来验证当服务器无人值守式到底发生了什么事情。

root@raspberrypi:~# uptime
 04:09:59 up 7 min,  1 user,  load average: 0.01, 0.31, 0.24

 

  • 命令:w

是否觉得命令’w’很滑稽?但是事实上不是的。它是一个命令,尽管只有一个字符长!命令”w“是uptimewho命令,以前后的顺序组合在一起。

  • 命令: top

显示CPU进程信息。这个命令自动刷新,默认是持续显示CPU进程信息,除非使用了中断指令(Ctrl+c)。

  • 命令: mkfs.ext4

这个命令在指定的设备上创建一个新的ext4文件系统,如果这个命令后面跟的是个错误的设备,那么整个设备就会被擦除和格式化,所以建议不要运行这个命令,除非你清楚自己正在干什么。

Mkfs.ext4 /dev/sda1 (sda1 block will be formatted)
mkfs.ext4 /dev/sdb1 (sdb1 block will be formatted)
  • lsof -i:80  找出80端口

  • tail -f  filename      监视filename文件的尾部内容(默认10行,相当于增加参数 -n 10),刷新显示在屏幕上。退出,按下CTRL+C。

linux下vi的复制,黏贴,删除,撤销,跳转等命令

一,模式
vi编辑器有3种模式:命令模式输入模式末行模式。掌握这三种模式十分重要:

命令模式:vi启动后默认进入的是命令模式,从这个模式使用命令可以切换到另外两种模式,同时无论在任何模式下只要按一下[Esc]键都可以返回命令模式。

输入模式:在命令模式中输入字幕“i”就可以进入vi的输入模式编辑文件。在这个模式中我们可以编辑、修改、输入等编辑工作,在编辑器最后一行显示一个“–INSERT–”标志着vi进入了输入模式。当我们完成修改输入等操作的时候我们需要保存文件,这时我们需要先返回命令模式,在进入末行模式保存。

末行模式:在命令模式输入“:”即可进入该模式,在末行模式中有好多好用的命令。

二,复制
a,复制整行
命令模式下,光标位于要复制的当前行,输入 yy
b,复制一个单词
命令模式下,光标位于要复制的当前单词的第一个字母,输入 yw

三,黏贴
命令模式下,输入 p

四,删除
a,删除整行
命令模式下,光标位于要删除的所在行,输入 dd

b,删除一个单词
命令模式下,光标位于要删除的单词的第一个字母,输入 dw

五,撤销
命令模式下,输入 u

六,跳转
命令模式下,输入 要跳转的行数,然后再输入 gg
如:要跳转到当前文件的第150行,输入 150gg

善用mysql中join的on条件内可以带and建立多条件join

mysql join on 可以带and,例如:
SELECT pa.name as name, pa.sn as sn, re.created, sl.sn, re.phase, rd.times, ABS(sl.quantity) as quantity, dr.name as dname, dr.specifications as specifications
FROM rr AS re JOIN red AS rd ON re.id = rd.rid JOIN drug AS dr ON dr.id = rd.did JOIN {{bbbb}} AS sl ON re.id = sl.r_id AND sl.d_id = rd.d_id JOIN pp AS pa ON pa.id = re.p_id
WHERE $where AND sl.receive_id >0
用于将被join表没有对应数据的时候也可以将主join表的数据显示出来

QQ截图20160530000552

phpcms更换编辑器由CKEditor为UEditor,简单两步,没有网上说的那么复杂…

phpcms更换编辑器由CKEditor为UEditor,简单两步,没有网上说的那么复杂,下面直接上操作图:

QQ截图20160526000200 QQ截图20160526000323

就以上 两步骤,去UEditor官网下载源码,这个谁都会。下载完直接丢进根目录下/statics/js/目录即可。如果还有不会的,那我就没办法。

以上仅为分享麦芒个人心得,希望广大码农们,一旦解决了一些问题,都把它们分享出来,让朋友们少走弯路。

Git 分支 – 分支的新建与合并

分支的新建与合并

让我们来看一个简单的分支新建与分支合并的例子,实际工作中你可能会用到类似的工作流。 你将经历如下步骤:

  1. 开发某个网站。
  2. 为实现某个新的需求,创建一个分支。
  3. 在这个分支上开展工作。

正在此时,你突然接到一个电话说有个很严重的问题需要紧急修补。 你将按照如下方式来处理:

  1. 切换到你的线上分支(production branch)。
  2. 为这个紧急任务新建一个分支,并在其中修复它。
  3. 在测试通过之后,切换回线上分支,然后合并这个修补分支,最后将改动推送到线上分支。
  4. 切换回你最初工作的分支上,继续工作。

新建分支

首先,我们假设你正在你的项目上工作,并且已经有一些提交。

一个简单的提交历史。

Figure 3-10. 一个简单提交历史

现在,你已经决定要解决你的公司使用的问题追踪系统中的 #53 问题。 想要新建一个分支并同时切换到那个分支上,你可以运行一个带有 -b 参数的 git checkout 命令:

$ git checkout -b iss53
Switched to a new branch "iss53"

它是下面两条命令的简写:

$ git branch iss53
$ git checkout iss53
创建一个新分支指针。

Figure 3-11. 创建一个新分支指针

你继续在 #53 问题上工作,并且做了一些提交。 在此过程中,iss53 分支在不断的向前推进,因为你已经检出到该分支(也就是说,你的 HEAD 指针指向了 iss53 分支)

$ vim index.html
$ git commit -a -m 'added a new footer [issue 53]'
iss53 分支随着工作的进展向前推进。

Figure 3-12. iss53 分支随着工作的进展向前推进

现在你接到那个电话,有个紧急问题等待你来解决。 有了 Git 的帮助,你不必把这个紧急问题和 iss53 的修改混在一起,你也不需要花大力气来还原关于 53# 问题的修改,然后再添加关于这个紧急问题的修改,最后将这个修改提交到线上分支。 你所要做的仅仅是切换回 master 分支。

但是,在你这么做之前,要留意你的工作目录和暂存区里那些还没有被提交的修改,它可能会和你即将检出的分支产生冲突从而阻止 Git 切换到该分支。 最好的方法是,在你切换分支之前,保持好一个干净的状态。 有一些方法可以绕过这个问题(即,保存进度(stashing) 和 修补提交(commit amending)),我们会在 储藏与清理 中看到关于这两个命令的介绍。 现在,我们假设你已经把你的修改全部提交了,这时你可以切换回 master 分支了:

$ git checkout master
Switched to branch 'master'

这个时候,你的工作目录和你在开始 #53 问题之前一模一样,现在你可以专心修复紧急问题了。 请牢记:当你切换分支的时候,Git 会重置你的工作目录,使其看起来像回到了你在那个分支上最后一次提交的样子。 Git 会自动添加、删除、修改文件以确保此时你的工作目录和这个分支最后一次提交时的样子一模一样。

接下来,你要修复这个紧急问题。 让我们建立一个针对该紧急问题的分支(hotfix branch),在该分支上工作直到问题解决:

$ git checkout -b hotfix
Switched to a new branch 'hotfix'
$ vim index.html
$ git commit -a -m 'fixed the broken email address'
[hotfix 1fb7853] fixed the broken email address
 1 file changed, 2 insertions(+)
基于 `master` 分支的紧急问题分支(hotfix branch)。

Figure 3-13. 基于 master 分支的紧急问题分支 hotfix branch

你可以运行你的测试,确保你的修改是正确的,然后将其合并回你的 master 分支来部署到线上。 你可以使用 git merge 命令来达到上述目的:

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

在合并的时候,你应该注意到了”快进(fast-forward)”这个词。 由于当前 master 分支所指向的提交是你当前提交(有关 hotfix 的提交)的直接上游,所以 Git 只是简单的将指针向前移动。 换句话说,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。

现在,最新的修改已经在 master 分支所指向的提交快照中,你可以着手发布该修复了。

`master` 被快进到 `hotfix`。

Figure 3-14. master 被快进到 hotfix

关于这个紧急问题的解决方案发布之后,你准备回到被打断之前时的工作中。 然而,你应该先删除hotfix 分支,因为你已经不再需要它了 —— master 分支已经指向了同一个位置。 你可以使用带 -d 选项的 git branch 命令来删除分支:

$ git branch -d hotfix
Deleted branch hotfix (3a0874c).

现在你可以切换回你正在工作的分支继续你的工作,也就是针对 #53 问题的那个分支(iss53 分支)。

$ git checkout iss53
Switched to branch "iss53"
$ vim index.html
$ git commit -a -m 'finished the new footer [issue 53]'
[iss53 ad82d7a] finished the new footer [issue 53]
1 file changed, 1 insertion(+)
继续在 `iss53` 分支上的工作。

Figure 3-15. 继续在 iss53 分支上的工作

你在 hotfix 分支上所做的工作并没有包含到 iss53 分支中。 如果你需要拉取 hotfix 所做的修改,你可以使用 git merge master 命令将 master 分支合并入 iss53 分支,或者你也可以等到 iss53 分支完成其使命,再将其合并回 master 分支。

分支的合并

假设你已经修正了 #53 问题,并且打算将你的工作合并入 master 分支。 为此,你需要合并 iss53 分支到 master 分支,这和之前你合并 hotfix 分支所做的工作差不多。 你只需要检出到你想合并入的分支,然后运行 git merge 命令:

$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html |    1 +
1 file changed, 1 insertion(+)

这和你之前合并 hotfix 分支的时候看起来有一点不一样。 在这种情况下,你的开发历史从一个更早的地方开始分叉开来(diverged)。 因为,master 分支所在提交并不是 iss53 分支所在提交的直接祖先,Git 不得不做一些额外的工作。 出现这种情况的时候,Git 会使用两个分支的末端所指的快照(C4C5)以及这两个分支的工作祖先(C2),做一个简单的三方合并。

一次典型合并中所用到的三个快照。

Figure 3-16. 一次典型合并中所用到的三个快照

和之间将分支指针向前推进所不同的是,Git 将此次三方合并的结果做了一个新的快照并且自动创建一个新的提交指向它。 这个被称作一次合并提交,它的特别之处在于他有不止一个父提交。

一个合并提交。

Figure 3-17. 一个合并提交

需要指出的是,Git 会自行决定选取哪一个提交作为最优的共同祖先,并以此作为合并的基础;这和更加古老的 CVS 系统或者 Subversion (1.5 版本之前)不同,在这些古老的版本管理系统中,用户需要自己选择最佳的合并基础。 Git 的这个优势使其在合并操作上比其他系统要简单很多。

既然你的修改已经合并进来了,你已经不再需要 iss53 分支了。 现在你可以在任务追踪系统中关闭此项任务,并删除这个分支。

$ git branch -d iss53

遇到冲突时的分支合并

有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。 如果你对 #53 问题的修改和有关 hotfix 的修改都涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突:

$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件:

$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:      index.html

no changes added to commit (use "git add" and/or "git commit -a")

任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。 出现冲突的文件会包含一些特殊区段,看起来像下面这个样子:

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
 please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

这表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在======= 的下半部分。 为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。 例如,你可以通过把这段内容换成下面的样子来解决冲突:

<div id="footer">
please contact us at email.support@github.com
</div>

上述的冲突解决方案仅保留了其中一个分支的修改,并且 <<<<<<< , ======= , 和 >>>>>>> 这些行被完全删除了。 在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。

如果你想使用图形化工具来解决冲突,你可以运行 git mergetool,该命令会为你启动一个合适的可视化合并工具,并带领你一步一步解决这些冲突:

$ git mergetool

This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge
Merging:
index.html

Normal merge conflict for 'index.html':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (opendiff):

如果你想使用除默认工具(在这里 Git 使用 opendiff 做为默认的合并工具,因为作者在 Mac 上运行该程序)外的其他合并工具,你可以在 “下列工具中(one of the following tools)” 这句后面看到所有支持的合并工具。 然后输入你喜欢的工具名字就可以了。

NOTE

如果你需要更加高级的工具来解决复杂的合并冲突,我们会在 高级合并 介绍更多关于分支合并的内容。

等你退出合并工具之后,Git 会询问刚才的合并是否成功。 如果你回答是,Git 会暂存那些文件以表明冲突已解决: 你可以再次运行 git status 来确认所有的合并冲突都已被解决:

$ git status
On branch master
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:

    modified:   index.html

如果你对结果感到满意,并且确定之前有冲突的的文件都已经暂存了,这时你可以输入 git commit 来完成合并提交。 默认情况下提交信息看起来像下面这个样子:

Merge branch 'iss53'

Conflicts:
    index.html
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
#	.git/MERGE_HEAD
# and try again.


# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
#	modified:   index.html
#

如果你觉得上述的信息不够充分,不能完全体现分支合并的过程,你可以修改上述信息,添加一些细节给未来检视这个合并的读者一些帮助,告诉他们你是如何解决合并冲突的,以及理由是什么。

万恶的dedecms,害我找了一晚上的Bug,居然是它惹的祸啊…

客户的一个老站点,最近客户反馈说怎么前台内容页都访问不了呢……

咨询了一下客户前后操作,客户只说重新生成了下后台,没做其它操作,我说这不可能导致内容页访问不了吧,紧接着开始找bug了……

T$R834[F8ISK(P)VOU~Y}9C

 

奇怪的问题在于:所有信息详情页的标题,时间,作者等都不见了,不管是动态还是静态都不显示。

尽然都不显示,并且有些都直接404页面,那就看看生成了什么诡异文件呢,ssh 进入服务器看了看,发现都生成了1970的文件夹,这都是时间文件夹,为什么时间会变成1970呢,百度,谷歌了一下,发现都是什么1970时间是因采集导致的问题,其它的问题就一概不知,也没见人提,这真是“邪乎”了。

0[[S)JLZ]%{Y_@MOKZLE@5J

不管如何修改后台进行生成,都无济于事,都还是生成1970的文件夹

很是纳闷。。。

翻了下代码:

4WQQ_A5SO[$IM8JZ10KJ$`H

一步步的查询,一步步的打断点,整整找了几个小时。。。

就在焦头烂额的时候,心想这下无解了吗,不可能

继续扫描代码,终于发现了,原来是在数据缓存上出了问题啊,缓存表上保存的栏目路径和实际栏目路径完全不是一回事,dedecms在配置文件缓存上需要有足够的权限才能访问,调整了权限后,对缓存表和实际栏目表对应起来,最终解决问题。

WordPress的手动升级步骤

WordPress的版本更新总是很迅速(修复大部分的bug),每次更新后我们大部分的时间会在后台去自动升级,可是国外大部分网站服务器被墙了,所以在更新的时候经常会自动升级失败,所以博主们不得不想办法去更新,所以只好想方设法去更新,下面将是手动更新的方法,其实方法很简单,在这里赘述只是在三的提示各博主几个问题,以免把数据给覆盖丢失了。

第一步、备份程序文件和数据库。不备份升级后出现问题的可能性也不大,但是为了以防万一还是备份一下吧,养成个好习惯。

第二步、登录后台关闭所有插件。网友提醒补充的一条,升级的时候别忘了哦。(这个经过亲身体会,感觉社不设置无副作用)

第三步、下载最新wordpress安装包。这个就简单了,wordpress.org去下也可直接博客后台下载。

第四步、解压安装包更新数据。将网站根目录下wp-admin和wp-includes两个目录中的文件换成最新下载的程序文件。

第五步、更新根目录下除wp-config.php文件以外的文件。wp-config.php文件是wp配置文件,包括数据库连接设置等,所以千万不要把此文件删除了。另外wp-content文件夹内的内容不用更改,这里面放的是主题文件,插件文件等,不在升级范围内,运行http://www.luzirq.com/wp-admin/upgrade.php,将你的博客地址填入路径中执行升级程序。

至此,WordPress手动升级工作全部完毕。灰常简单吧。

wordpress

SEO新手必看基础:URL优化之URL长度

URL优化就是指通过对URL各组成部分进行适当的调整,以提高URL搜索引擎的友好性。

它包括三部分:

第一,对域名、目录、文件的命名;

第二,分隔符的使用;

第三URL长度及关键字词频的控制。这三部分相互制约、相互影响。在优化的过程中,我们必须掌握这三部分的内在联系,对各个部分进行充分的协调,这样才能达到最佳优化效果,否则将功败垂成。

SEO优化

URL优化是网站优化的六大重要环节之一,占据着重要的地位,不仅在决定页面相关性方面起着重要的作用,更重要的是URL还会直接影响搜索引擎对页面的收录。

搜索引擎在抓取页面的时候,对于页面的URL长度会存在一定的限制,对于超过限定长度的URL所指向的页面,搜索引擎就可以放弃收录,决定URL长度的主要因素包括域名的长度、路径长度、文件名长度。简单描述几点:

    
    1. 域名长度
    域名长度是指“子域名”“域名名称”“域名类型”所占用的字符数,例如:www.luzirq.com子域名是www.域名是luzirq.com,域名类型com,则域名长度14.
   
    2. 路径长度
    路径长度是指文件存放在路径的名称所占用的字符数,路径长度=目录名称长度+目录2名称长度+…+目录N名称长度。
  
    3. 文件名长度
    文件名长度是指文件名称所占用的字符数,例如:www.luzirq.com占用字符数,其文件名长度为10.
    4. URL长度
    综上述,URL程度=类型+域名长度+路径长度+文件名长度。
    5. URL长度的影响
    搜索引擎在抓取页面的时候,对页面的URL长度是有一定的限制的。对于超过这个限制的页面搜索引擎就可能会放弃收录。而且,页面的URL越短,得到的权重就越高。
假如这两个页面一样那么URL1比URL2的权重更高,在目录的深度角度考虑。URL1比URL2更浅。

URL优化

看到了Windows的未来—–windows-Bash-Ubuntu

windows的未来渐渐的走向linux模式,也再朝向开发者靠近了,这是好事吗?

QQ截图20160408225539

s_999ee5a9fb914860bd1d1907a5d98ba0

今天凌晨的Build 2016大会上,微软为开发者尤其是Linux/Unix的开发者带来了好消息,Windows 10将原生整合Linux命令行工具Bash,也就意味着不再需要借助虚拟机进行编译工作。

我们知道,绝大多数Linux发行版都使用BASH作为其默认的标准Shell,地位极其重要。

而且横向对比Windows平台的cmd来看Linux的终端字体好看、功能强大,微软称,Bash命令行工具将在Windows应用商店中提供下载

此次,Bash能进驻Windows,得益于和著名Linux发行商Canonical的合作。

Git 常用命令整理

最近在公司的服务器上安装了Git Sever,开始从SVN转向到Git了,整理了一些在Git常用的命令。

取得Git仓库

初始化一个版本仓库

git init

Clone远程版本库

git clone git@xbc.me:wordpress.git

添加远程版本库origin,语法为 git remote add [shortname] [url]

git remote add origin git@xbc.me:wordpress.git

查看远程仓库

git remote -v

提交你的修改

添加当前修改的文件到暂存区

git add .

如果你自动追踪文件,包括你已经手动删除的,状态为Deleted的文件

git add -u

提交你的修改

git commit –m &quot;你的注释&quot;

推送你的更新到远程服务器,语法为 git push [远程名] [本地分支]:[远程分支]

git push origin master

查看文件状态

git status

跟踪新文件

git add readme.txt

从当前跟踪列表移除文件,并完全删除

git rm readme.txt

仅在暂存区删除,保留文件在当前目录,不再跟踪

git rm –cached readme.txt

重命名文件

git mv reademe.txt readme

查看提交的历史记录

git log

修改最后一次提交注释的,利用–amend参数

git commit –amend

忘记提交某些修改,下面的三条命令只会得到一个提交。

git commit –m &quot;add readme.txt&quot;
git add readme_forgotten
git commit –amend

假设你已经使用git add .,将修改过的文件a、b加到暂存区

现在你只想提交a文件,不想提交b文件,应该这样

git reset HEAD b

取消对文件的修改

git checkout –- readme.txt

基本的分支管理

创建一个分支

git branch iss53

切换工作目录到iss53

git chekcout iss53

将上面的命令合在一起,创建iss53分支并切换到iss53

git chekcout –b iss53

合并iss53分支,当前工作目录为master

git merge iss53

合并完成后,没有出现冲突,删除iss53分支

git branch –d iss53

拉去远程仓库的数据,语法为 git fetch [remote-name]

git fetch

fetch 会拉去最新的远程仓库数据,但不会自动到当前目录下,要自动合并

git pull

查看远程仓库的信息

git remote show origin

建立本地的dev分支追踪远程仓库的develop分支

git checkout –b dev origin/develop

Nginx实战基础篇五 如何让用户通过用户名密码认证访问我们的web站点

Nginx实战基础篇五 如何让用户通过用户名密码认证访问我们的web站点

有时我们会有这么一种需求,就是你的网站并不想提供一个公共的访问或者某些页面不希望公开,我们希望的是某些特定的客户端可以访问。那么我们可以在访问时要求进行身份认证,就如给你自己的家门加一把锁,以拒绝那些不速之客。

实验环境:

现在公司开通了一个内部使用网站为http://www.luzirq.com,要求所有人查看网页信息之前都必须要输入内定的用户名及密码方可浏览网页

http://www.luzirq.com进行测试。

http://www.luzirq.com 192.168.100.107

DNS1 192.168.100.102

一、查看当前系统参数

  1. [root@rhel6u3-2 ~]# uname –r  //查看系统内核版本号
  2. 2.6.32-279.el6.i686
  3. [root@rhel6u3-2 ~]# cat /etc/redhat-release //查看系统版本号
  4. Red Hat Enterprise Linux Server release 6.3 (Santiago)

 

二、编辑虚拟主机配置文件

 

  1. [root@rhel6u3-7 ~]# vim /usr/local/nginx/conf/nginx.conf //主配置文件中http字段中添加以下语句,将虚拟主机的配置文件指向www.luzirq.com
  2. include /usr/local/nginx/server/www.luzirq.com;
  3. [root@rhel6u3-7 ~]# vim /usr/local/nginx/server/www.luzirq.com
  4. server {
  5.      listen       80;  //监听端口为80
  6.      server_name  www.luzirq.com;  //虚拟主机网址
  7.       location / {
  8.             root   sites/www1;  //虚拟主机网站根目录
  9.             index  index.html index.htm;  //虚拟主机首页
  10.             auth_basic “secret”;  //虚拟主机认证命名
  11.             auth_basic_user_file /usr/local/nginx/passwd.db; //虚拟主机用户名密码认证数据库
  12.         }
  13.         location /status {
  14.                 stub_status on;  //开启网站监控状态
  15.                 access_log /usr/local/nginx/logs/www.luzirq.com; //监控日志
  16.                 auth_basic “NginxStatus”; }
  17.     }

 

三、通过htpasswd命令生成用户名及对应密码数据库文件。

 

  1. [root@rhel6u3-7 server]# htpasswd -c /usr/local/nginx/passwd.db username  //创建认证信息,username为认证用户名
  2. New password: *******  //输入认证密码
  3. Re-type new password: ********  //再次输入认证密码
  4. Adding password for user username
  5. [root@rhel6u3-7 server]#
  6. [root@rhel6u3-7 ~]# chmod 400 /usr/local/nginx/passwd.db  //修改网站认证数据库权限
  7. [root@rhel6u3-7 ~]# chown nginx.  /usr/local/nginx/passwd.db  //修改网站认证数据库属主和属组
  8. [root@rhel6u3-7 ~]# cat /usr/local/nginx/passwd.db  //可以看到通过htpasswd生成的密码为加密格式
  9. username:8eZAz7BqcrXmY
  10. [root@rhel6u3-7 ~]#

 

四、平滑重启nginx服务

 

  1. [root@rhel6u3-7 ~]# /etc/rc.d/init.d/nginx reload  //平滑重启nginx服务
  2. nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
  3. nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
  4. Reloading nginx:                                           [  OK  ]

 

五、DNS服务器上添加www1 A记录

 

  1. www    A   192.168.100.107

 

最后至为关键的位置(独门绝技,此方法在网上是无法搜到的):对于nginx环境的linux是不支持htpasswd命令的,它是属于apache下的,需要安装httpd才行,但是在nginx环境下安装,难免会出现冲突,安装nginx和apache非常复杂,没有lnmpa是不很难配置成功了。网上不管怎么搜,都是搜不到解决方案的,武汉网站建设在这里献上亲自经历的方法:在本地的apache下用htpasswd生成密码串,然后从本地生成之后复制到nginx上。或者自己写一个php代码,武汉网站建设也献上下载。

nginx环境htpasswd下载

个人认为比较有用的win10系统快捷键

win10系统渐渐替换了win8.1,一些改进确实耳目一新,不过最大特点还是回归了,下面是一些个人认为比较重要的快捷键:

Win+C:强制调出Charm栏。

Win+左/右/上/左上/左下/右上/右下:将窗口快速缩放至1/2分屏、1/4分屏,其中1/4分屏为Win10新增功能,对应快捷键为Win+左上/左下/右上/右下。

Win+E:调出“主页”窗口。“主页”是Win10新增功能,包含最近访问文件夹、最近访问文件、收藏夹等,以资源管理器作为载体。

Win+Home:仅保留当前窗口,其余窗口最小化。

Win+Enter:直接启动“讲述人”。

Win+数字键:快速打开任务栏上已固定应用,比如Win+1打开第一个应用、Win+2打开第二个应用……以此类推,同时支持Metro应用。

Win+T:在任务栏图标间切换,但不打开,相当于鼠标悬停。

Alt+Tab:窗口切换器,当然Win10已经将它改进了,新版缩略图更大,并且是全屏显示。

Win+Tab:Win7时代的Flip3D(3D窗口切换器),到了Win10中变成了虚拟桌面切换器。嗯!和点击任务栏上那个按钮一个效果!

Ctrl+Shift+ESC:直接打开任务管理器。

Alt+左/右/上:快速跳转至上一个文件夹/下一个文件夹/父文件夹(仅限资源管理器)。

F11:沉浸式传统窗口布局(仅限传统程序)。

Win+Ctrl+左/右:切换当前虚拟桌面。

Win+Ctrl+D:建立新虚拟桌面。

Win+Ctrl+F4:关闭当前虚拟桌面(已打开窗口会自动移动到下一个桌面,不会丢失!)。

Win+D:显示传统桌面(即窗口最小化,沉浸式Metro需按动两下)。

Win+I:打开Charm栏→设置菜单(非新版Charm菜单)。

Win+X:打开简易版开始菜单,这个用来启动一些系统级程序还是很方便的。

Win+Prt Sc:屏幕截图。按下该快捷键后,屏幕会瞬间暗一下,并伴有“咔嚓”一声,视觉感和手机上的截屏软件很像,截图自动存放至“图片”文件夹。

Ctrl+V:这是Win10命令提示符里新增的,功能就是将剪切板内容直接粘贴到提示符内。而在此之前,这组快捷键所能得到的结果,仅仅是一个^v。

以上是笔者结合自己经验,挑选的一些日常使用率较高的快捷键,诸如大家熟悉的Win+L、Win+R之类并未涉及。当然Win10是一款全新系统,短短两三周的试用是不可能将其探寻完整的。如果你在试用过程中也发现了一些不一样的按钮,也欢迎和我们一同分享,祝大家Win10玩得愉快!

win10|系统快捷键

win10|系统快捷键

DEDECMS织梦 真正的随机文章的调用方法

关于dedecms随机文章是老生常谈了,原本很简单的一问题,现在还是捡起来说说,供大家借鉴一下吧

大家都知道随机标签 rand,调用标签也知道怎么写:

{dede:arclist row=’1000′ pagesize=’10’ titlelen=’35’ orderby=’rand’}

[field:textlink/]

{/dede:arclist}

但是仅仅有这个,在静态页面上是不能达到真正意义上的随机的,下面就是如何设置了:

将你需要随机生成的那段代码(上面调用标签)加入到新建自定义宏中,然后使用JS调用,将JS代码插入到模板中
如下:
<script src=’/plus/mytag_js.php?aid=12&nocache=1′ language=’javascript’></script>
通过后台的JS调用生成的JS代码是没有nocache=1

为了能兼容多个版本,建议nocache=1还是加上为好,这样直接在前台需要的地方复制上面的这个js代码即可调用随机代码了。

phpcms那点事——setting_models

关于phpcms的setting_models[”]一说,网站建设麦芒在这里简单说下:

今天在做phpcms的二次开发的时候,突然遇到一个不解的问题,一客户要求将phpcms的网页模块进行二次开发,在phpcms\modules\yp\index.php文件里面就有如下的一段代码:

//列表页推荐位ID,模块配置推荐位第二个为列表页推荐位配置
$posid = intval($this->setting[‘position’][2][‘posid’]);
$siteid = SITEID;
$SEO = seo(SITEID, ”, $this->setting[‘seo_title’], $this->setting[‘seo_description’], $this->setting[‘seo_keywords’]);
//产品modelid
$product_id = $this->setting_models[73];
$buy_id = $this->setting_models[76];
$news_id = $this->setting_models[72];//这句为麦芒添加

看到如何得来”产品modelid“感觉很困惑,因为麦芒想得到”news_id”,所以才困惑不解的。

困惑点就是setting_models 里面为什么是73、76、72 ???

在数据中到处进行了查找,发现并没有任何的蛛丝马迹?难道这个setting_models里面的数字无中生有,我觉得不可能,程序中一切皆对象,不相信不存在…

编者麦芒就通过不断的var_dump()去调试,终于找到了缘由,原来$this->setting_models是一缓存数组,显然缓存是由文件缓存函数来生成的…  到目前为止,终于真相大白了

 

今天是一个好日子,luz工作室博客在今天正式上线

准备了几载,终于在今天,http://www.luzirq.com 正式上线了,为什么非要选择今天呢,在今后的每一天请听武汉建站luz工作室一一道来……

武汉建站luz工作室是一个集网站建设,网站优化,seo,仿站,软件开发,网页制作,源码修改等网络技术开发的帮助一切所需要的企业及个人排忧解难的一个团体。

关于这个工作室的更多详尽的介绍,也将在后面慢慢的”浮出水面“。

你真的懂git rebase吗?

前段时间由于某种原因,开始接手开发公司前端Vue搭建的项目

该前端项目采用的是基于git rebase的形式去合并代码,而我之前使用git一直都是采用merge的形式合并分支代码,对于rebase一概不知

故此利用碎片时间学习整理一下关于git rebase的原理以及其和git merge的区别是什么,我会采用实际的案例描述二者的区别

准备工作

  • git 客户端安装(只要git bash即可)
  • github上新建一个项目

模拟日常开发

同学A:

  • 执行git log
4

可以看出此时该项目仅有一次提交记录

  • 执行新增文件a.txt,并本地提交一次后再次执行git log
5

这个时候打开github,刷新该项目的commit记录

6

发现远程仓库还是只有一次提交记录的,说明A同学还没有将自己最新的修改push到远程仓库,其他同学这个时候是看不到A的最新提交的

  • A同学将自己的最新提交Push到远程仓库
7
  • 再次刷新github 提交记录,发现已经多了一个A同学提交的最新记录了

切分支开发

  • 基于已有两次提交记录的本地master分支检出一个新分支dev,并将该分支推到远程仓库
8
  • 查看远程仓库,多了一个dev分支
10

A同学开发功能

假设A同学基于dev分支开发功能,在本地新做了三次代码提交,git log
如下

  • 重点

如果此时在A同学准备进行第四次本地提交之前,另一个同学B向远程仓库推送了一个master分支的提交,即此时master实际的提交已经向前走了

我们这个时候在github上操作一次commit,模拟另一个同学此时push了master分支

  • A同学本地更新一下master分支

发现master分支已经向前走了一次提交

此时我们知道A同学开发的dev分支是基于C2提交点切出来的,而这个时候master分支已经被更新了

如果A同学开发完毕,需要将其所作的功能合并到master分支 ,他可以有两种选择

直接git merge

如果A同学选择用git merge的方式进行合并dev到master分支,那么git会这么做

  1. 找出dev分支和master分支的最近共同祖先commit点,即C2
  2. 将dev最新一次commit(C5)和master最新一次commit(C6)合并后生成一个新的commit(C7),有冲突的话需要解决冲突
  3. 将以上两个分支dev和master上的所有提交点(从C2以后的)按照提交时间的先后顺序进行依次放到master分支上

git rebase 后再git merge

  1. rebase之前需要经master分支拉到最新
  2. 切换分支到需要rebase的分支,这里是dev分支
  3. 执行git rebase master,有冲突就解决冲突,解决后直接git add . 再git rebase –continue即可

 

可以发现其一并没有多出一次commit,其二dev后面几次提交的commit hash值已经变了,包括C3,C4,C5

  1. 切换到master分支,执行git merge dev

发现采用rebase的方式进行分支合并,整个master分支并没有多出一个新的commit,原来dev分支上的那几次(C3,C4,C5)commit在rebase之后其hash值发生了变化,不在是当初在dev分支上提交的时候的hash值了,但是提交的内容被全部复制保留了,并且整个master分支的commit记录呈线性记录

 

总结

  • git merge 操作合并分支会让两个分支的每一次提交都按照提交时间(并不是push时间)排序,并且会将两个分支的最新一次commit点进行合并成一个新的commit,最终的分支树呈现非整条线性直线的形式
  • git rebase操作实际上是将当前执行rebase分支的所有基于原分支提交点之后的commit打散成一个一个的patch,并重新生成一个新的commit hash值,再次基于原分支目前最新的commit点上进行提交,并不根据两个分支上实际的每次提交的时间点排序,rebase完成后,切到基分支进行合并另一个分支时也不会生成一个新的commit点,可以保持整个分支树的完美线性

另外值得一提的是,当我们开发一个功能时,可能会在本地有无数次commit,而你实际上在你的master分支上只想显示每一个功能测试完成后的一次完整提交记录就好了,其他的提交记录并不想将来全部保留在你的master分支上,那么rebase将会是一个好的选择,他可以在rebase时将本地多次的commit合并成一个commit,还可以修改commit的描述等

最后

如果你想要你的分支树呈现简洁,不罗嗦,线性的commit记录,那就采用rebase

否则,就用merge吧