​​​​ git 笔记 | 苏生不惑的博客

git 笔记

linux

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
https://www.itcodemonkey.com/article/12558.html
[alvin@VM_0_16_centos ~]$ whoami
alvin
查看当前登录到服务器的用户有哪一些。

[alvin@VM_0_16_centos ~]$ who
alvin pts/0 2018-12-09 07:25 (116.199.***.***)
root pts/1 2018-12-09 11:05 (116.199.***.***)
alvin pts/2 2018-12-09 11:05 (116.199.***.***)
harry pts/3 2018-12-09 11:06 (116.199.***.***)
kate pts/4 2018-12-09 11:08 (116.199.***.***)
alvin pts/5 2018-12-09 11:53 (116.199.***.***)
在显示结果里,第一列是用户名;第二列是连接的终端,tty 表示显示器,pts 表示远程连接;第三列是登陆时间。

这里信息稍微多一些,但如果我们只想知道谁在线要怎么操作?只需用 users 命令来查看即可。

[alvin@VM_0_16_centos ~]$ users
alvin alvin alvin harry kate root
显示已经登录系统的用户的名称,以及他们正在做的事
[alvin@VM_0_16_centos ~]$ w
16:25:54 up 29 days, 6:05, 6 users, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
alvin pts/0 116.199.***.** 07:25 2.00s 0.11s 0.00s w
root pts/1 116.199.***.** 11:05 5:20m 0.02s 0.02s -bash
alvin pts/2 116.199.***.** 11:05 5:20m 0.04s 0.05s sshd: alvin [priv]
harry pts/3 116.199.***.** 11:06 4:33m 18.08s 18.06s watch date
kate pts/4 116.199.***.** 11:08 4:33m 10.51s 10.48s top
alvin pts/5 116.199.***.** 11:53 4:32m 0.02s 0.02s -bash
[alvin@VM_0_16_centos ~]$ w alvin
16:34:21 up 29 days, 6:14, 6 users, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
alvin pts/0 116.199.***.** 07:25 5.00s 0.12s 0.06s sshd: alvin [priv]
alvin pts/2 116.199.***.** 11:05 5:28m 0.04s 0.05s sshd: alvin [priv]
alvin pts/5 116.199.***.** 11:53 4:40m 0.02s 0.02s -bash
last命令可用于显示特定用户登录系统的历史记录
[alvin@VM_0_16_centos ~]$ last alvin
alvin pts/5 116.199.***.** Sun Dec 9 11:53 still logged in
alvin pts/2 116.199.***.** Sun Dec 9 11:05 still logged in
alvin pts/0 116.199.***.** Sun Dec 9 07:25 still logged in
alvin pts/0 116.199.***.** Sat Dec 8 20:42 - 23:10 (02:28)
alvin pts/0 119.33.***.** Mon Dec 3 20:50 - 23:51 (1+03:01)
alvin pts/0 119.33.***.** Thu Nov 29 20:20 - 22:45 (02:24)
alvin pts/0 223.104.***.** Thu Nov 29 06:46 - 07:00 (00:14)
alvin pts/0 223.104.***.** Wed Nov 28 20:45 - 22:27 (01:42)
[alvin@VM_0_16_centos ~]$ sudo pkill -kill -t pts/3
#harry用户已经被踢除了
[alvin@VM_0_16_centos ~]$ w
17:04:37 up 29 days, 6:44, 5 users, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
alvin pts/0 116.199.102.65 07:25 5.00s 0.12s 0.00s w
root pts/1 116.199.102.65 11:05 5:59m 0.02s 0.02s -bash
alvin pts/2 116.199.102.65 11:05 5:59m 0.04s 0.05s sshd: alvin [priv]
kate pts/4 116.199.102.65 11:08 5:12m 11.94s 11.91s top
alvin pts/5 116.199.102.65 11:53 5:10m 0.02s 0.02s -bash

回到远程仓库的状态

1
git fetch --all && git reset --hard origin/master

重设第一个commit

1
git update-ref -d HEAD

删除已经合并到master的分支

1
git branch --merged master | grep -v '^\*\|  master' | xargs -n 1 git branch -d

展示本地分支关联远程仓库的情况

1
2
3
git branch -vv
ai_notice 6fa631e7 Merge branch 'master' into ai_notice
delete_msg 33fc3808 Merge branch 'master' into delete_msg

关联远程分支

1
2
git branch -u origin/mybranch
git push origin/mybranch -u

列出所有远程分支

1
git branch -r

列出本地和远程分支

1
git branch -a

从远程分支中创建并切换到本地分支

1
git checkout -b <branch-name> origin/<branch-name>

删除远程分支

1
2
3
4
git push origin --delete <remote-branchname>
或者

git push origin :<remote-branchname>

重命名本地分支

1
git branch -m <new-branch-name>

切回到某个标签

1
git checkout -b branch_name tag_name

放弃工作区的修改

1
2
3
4
git checkout <file-name>
放弃所有修改:

git checkout .

修改远程仓库的url

1
git remote set-url origin <URL>

查看两个星期内的改动

1
git whatchanged --since='2 weeks ago'

展示简化的commit历史

1
git log --pretty=oneline --graph --decorate --all

展示任意分支某一文件的内容

1
git show <branch-name>:<file-name>

clone下来指定的单一分支

1
git clone -b <branch-name> --single-branch https://github.com/user/repo.git

忽略某个文件的改动

1
2
3
4
5
6
关闭 track 指定文件的改动,也就是 Git 将不会在记录这个文件的改动

git update-index --assume-unchanged path/to/file
恢复 track 指定文件的改动

git update-index --no-assume-unchanged path/to/file

在commit log中查找相关内容

1
git log --all --grep='<given-text>'

搭建Git服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
https://coffeephp.com/articles/3
$ sudo yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel
$ sudo yum install git
$ sudo adduser git
$ cd /home/git
$ mkdir .ssh && chmod 700 .ssh
$ touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys
$ sudo chown -R git:git .ssh

客户端上生成密钥#

$ cd ~
$ ssh-keygen -t rsa
$ scp ~/.ssh/id_rsa.pub root@server_ip:/home/git/.ssh/authorized_keys

$ mkdir /home/git/repo/
$ sudo chown git:git /home/git/repo/
$ cd /home/git/repo/
$ sudo git init --bare sample.git
$ sudo chown -R git:git sample.git

$ git clone git@118.24.158.116/:/home/git/repo/sample.git sample
$cd sample
$ touch index.html
$ git add index.html
$ git commit index.html -m 'first commit'
$ git push origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 209 bytes | 209.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To 118.24.158.116:/home/git/repo/sample.git
* [new branch] master -> master
创建网站的目录#

$ sudo mkdir /var/www/sample -p
$ sudo chown -R git:git /var/www/sample

设置git钩子#

$ cd /home/git/repo/sample.git/hooks
$ sudo vim post-receive

写入以下内容:

#!/bin/sh
GIT_WORK_TREE=/var/www/sample git checkout -f

写入权限

$ sudo chmod +x post-receive

[root@VM_0_14_centos hooks]# ll /var/www/sample/
total 4
-rw-rw-r-- 1 git git 5 Jan 9 14:23 index.html

$ ssh git@118.24.158.116
Last failed login: Wed Jan 9 09:38:59 CST 2019 from 219.246.78.17 on ssh:notty
There were 264 failed login attempts since the last successful login.
[git@VM_0_14_centos ~]$ ll
total 4
drwxr-xr-x 3 git git 4096 Jan 9 14:16 repo
[git@VM_0_14_centos ~]$ ll repo/
total 4
drwxr-xr-x 7 git git 4096 Jan 9 14:23 sample.git
[git@VM_0_14_centos ~]$ ll repo/sample.git/
total 36
drwxr-xr-x 2 git git 4096 Jan 9 14:16 branches
-rw-r--r-- 1 git git 66 Jan 9 14:16 config
-rw-r--r-- 1 git git 73 Jan 9 14:16 description
-rw-r--r-- 1 git git 23 Jan 9 14:16 HEAD
drwxr-xr-x 2 git git 4096 Jan 9 14:21 hooks
-rw-rw-r-- 1 git git 112 Jan 9 14:23 index
drwxr-xr-x 2 git git 4096 Jan 9 14:16 info
drwxr-xr-x 10 git git 4096 Jan 9 14:23 objects
drwxr-xr-x 4 git git 4096 Jan 9 14:16 refs

[root@VM_0_14_centos hooks]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
/usr/bin/fish
$ which git-shell # make sure git-shell is installed on your system.
/usr/bin/git-shell
$ sudo vim /etc/shells # and add the path to git-shell from last command

使用 chsh 命令修改任一系统用户的 shell

$ sudo chsh git # and enter the path to git-shell, usually: /usr/bin/git-shell
Changing shell for git.
New shell [/bin/bash]: /usr/bin/git-shell
Shell changed.
这样,用户 git 就只能利用 SSH 连接对 Git 仓库进行推送和拉取操作,而不能登录机器并取得普通 shell。 如果试图登录,你会发现尝试被拒绝,像这样:

$ ssh git@118.24.158.116
Last login: Wed Jan 9 14:29:56 2019 from 218.30.113.34
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
Connection to 118.24.158.116 closed.

查看定时任务日志

1
2
3
4
5

默认位于 /var/log/cron 文件:

tail -f /var/log/cron
cat /var/log/cron | grep "sh"

GitHub API limit

1
2
3
4
5
GitHub API limit (0 calls/hr) is exhausted, could not fetch https://api.github.com/graphql. Create a GitHub OAuth token to go over the API rate limit. You can also wait until 2019-01-25 09:36:32 for the rate limit to reset.

Head to https://github.com/settings/tokens/new?scopes=repo&description=Composer+on+BJ-D-212361A+2019-01-25+0835
to retrieve a token. It will be stored in "C:/Users/xxx/AppData/Roaming/Composer/auth.json" for future use by Composer.
Token (hidden):

在Git中添加忽略文件

如果文件已经添加到缓存区了
// 移除file1
git reset HEAD file1
// 移除全部https://blog.tedxiong.com/add_ingore_file_for_git.html
git reset HEAD *
//如果有多个文件可以使用通配符
git rm –cached FILENAME
添加忽略文件
touch .gitignore
echo ‘file1’ >> .gitignore
echo ‘build/‘ >> .gitignore
配置全局的忽略文件
git config –global core.excludesfile ~/.gitignore_global
添加例外
如果不想跟别人分享.gitignore文件,可以在.git/info/exclude中配置规则。

一键提交脚本

1
2
3
4
5
6
7
vi push.sh
time=`date "+%Y-%m-%d_%H-%M-%S"`
who=`hostname'
git add --all
git commit -m "${who} push @ ${time}"
git push origin master
echo "Finished Push"

免密登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
ssh-keygen -t rsa
ssh-copy-id -i/Users/USERNAME/.ssh/id_rsa.pub root@ip
touch authorized_keys
chmod 600 /root/.ssh/authorized_keys
cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
ssh root@ip
如果此时想让其他人也免密登录 可以把本地的id_rsa 文件拷贝给别人 执行命令

ssh -i id_rsa root@ip
vim /etc/ssh/sshd_config
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys
PasswordAuthentication no #修改之前一定要确认你的秘钥可以正常使用
重启ssh配置生效

service sshd restart
从服务器下载

[username@host ~]$ cd ~/.ssh

[username@host ~]$ ssh-keygen // 一路回车

[username@host ~]$ cat id_rsa.pub >> authorized_keys

[username@host ~]$ chmod 600 authorized_keys

[username@host ~]$ chmod 700 ~/.ssh
// 下载私钥

[local@host ~]$ sudo scp -i USERNAME@HOST /usr/USERNAME/.ssh/id_rsa /LOCAL_PATH/id_rsa

// 测试秘钥登录

sudo ssh USERNAME@HOST -i /LOCAL_PATH/id_rsa

最近24小时修改过的文件

find / -mtime -1

修改 hostname

hostname syyong # 临时修改 hostname 为 syyong
vi /etc/sysconfig/network –> HOSTNAME = syyong # 永久修改 hostname 为syyong

查找文件

1
2
3
4
5
6
7
8
find /etc/ -name httpd.conf # 在 /etc 目录下查找文件名为 httpd.conf
find /etc/ -name http* # 在 /etc目录下以 httpd 开头的文件
find /root/ -size +10M # 在 /root 目录下大于 10M 的文件
find /home/ -user syyong # 在 /home 目录下查找所有者是 syyong
find ./ -user syyong -exec rm -rf{}\ # 在当前目录下把找到所有者是 syyong 的用户的文件删除掉
find /etc -cmin -5 # 在 /etc 目录下查找5分钟内修改过属性的文件和目录
find /etc -size +163840 -a -size -204800 # 在 /etc 目录下查找大于 80M 小于 100M 的文件
find .|xargs grep -ri "lnmp" # 在当前目录下查找含 lnmp 字符的文件

ssh

1
2
ssh -p 22 syyong@192.168.1.2 # 通过 ssh 通过账号密码登录到 192.168.1.2 服务器
ssh -i ./ssh-key.pem syyong@192.168.1.2 # 通过 ssh 通过证书登录到 192.168.1.2 服务器

scp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
scp -p 2202 /home/lnmp.tar.gz www@192.168.1.2:/home/ # 将文件 lnmp.tar.gz 同步到 192.168.1.2 服务器的 /home/ 目录下
rsync -avzP /home/lnmp.tar.gz -e 'ssh -p 2202' www@192.168.1.2:/home/ # 将文件 lnmp.tar.gz 增量同步到 192.168.1.2 服务器的 /home/ 目录下
touch file{1..100} # 批量创建 file1,file2...file100
touch file{a..z} # 批量创建 filea,fileb...filez
touch file{A..Z} # 批量创建 fileA,fileB...fileZ
echo 'lnmp' > lnmp.txt # 覆盖式写入 lnmp 到 lnmp.txt 文件中
echo 'lnmp' >> lnmp.txt # 追加式写入 lnmp 到 lnmp.txt 文件中

tar -xzvf syyong.tar.gz # 解压 gz 文件
unzip syyong.zip -d /home # 解压 zip 文件到 /home 目录下
tar -czvf syyong syyong.tar.gz # 将文件压缩成 gz 文件
zip -r syyong.zip syyong # 压缩 syyong 目录为 zip 文件
pkill php-fpm # 杀掉所有 php-fpm 进程
killall php-fpm # 杀掉所有 php-fpm 进程
netstat -tunpl|grep 80 # 查看端口使用情况
tcpdump -i eth0 # 监听eth0网卡数据
rpm -q xxx # 查看 xxx 软件是否已安装
rpm -qa # 查看已安装了的所有的 rpm 包
rpm -ivh /home/xxx.rpm # 按路径安装 xxx.rpm 软件包并显示进度
rpm -e xxx.rpm # 删除 xxx rpm 包
yum install xxx # 安装 xxx 软件
yum search xxx # 在 yum 仓库中查找 xxx 软件
yum remove xxx # 卸载 xxx 软件
init 0 # 关机
init 1 # 进入单用户模式
init 5 # 进入图形化登录界面
init 6 # 重启
nohup php index.php # 以 nohup 方式运行 index.php 脚本,这样关闭终端操作不影响程序的继续运行
time php index.php # 统计显示执行 index.php 脚本耗时情况
curl -o /dev/null -s -w %{time_namelookup}::%{time_connect}::%{time_starttransfer}::%{time_total}::%{speed_download}"\n" "http://www.syyong.com" # 查看访问站点的 rt
grep -> 过滤
cut -> 切割,从一个文本文件或者文本流中提取文本列
sort -> 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出
xargs -> 读入 stdin 的数据,并且以空格符或断行字符作为分辨,将 stdin 的数据分隔成为 arguments
uniq -> 去除重复行
wc -> 统计文件里面有多少单词,多少行,多少字符
awk '{print $0}' 2016.log # 输出 2016.log 的每行数据
awk '!arr[$1]++' 2016.log |wc -l # 统计 2016.log 中不重复的行的个数
rz -bye # 会弹出文件窗口,选择本地要上传的文件即可上传
sz file1 file2 # 下载 file1、file2 文件到本地
yum install lrzsz # 安装 lrzsz 软件

netstat 命令查看连接数判断攻击

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
显示所有活动的网络连接。

#netstat -na
查看同时连接到哪个服务器IP比较多,cc攻击用。使用双网卡或多网卡可用。

# netstat -an|awk '{print $4}'|sort|uniq -c|sort -nr|head
查看哪些IP连接到服务器连接多,可以查看连接异常IP。

#netstat -an|awk -F: '{print $2}'|sort|uniq -c|sort -nr|head
显示所有80端口的网络连接并排序。这里的80端口是http端口,所以可以用来监控web服务。如果看到同一个IP有大量连接的话就可以判定单点流量攻击了。

#netstat -an | grep :80 | sort
这个命令可以查找出当前服务器有多少个活动的 SYNC_REC 连接。正常来说这个值很小,最好小于5。 当有Dos攻击或的时候,这个值相当的高。但是有些并发很高的服务器,这个值确实是很高,因此很高并不能说明一定被攻击。

#netstat -n -p|grep SYN_REC | wc -l
列出所有连接过的IP地址。

#netstat -n -p | grep SYN_REC | sort -u
列出所有发送SYN_REC连接节点的IP地址。

#netstat -n -p | grep SYN_REC | awk '{print $5}' | awk -F: '{print $1}'
使用netstat命令计算每个主机连接到本机的连接数。

#netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
列出所有连接到本机的UDP或者TCP连接的IP数量。

#netstat -anp |grep 'tcp|udp' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n
检查 ESTABLISHED 连接并且列出每个IP地址的连接数量。

#netstat -ntu | grep ESTAB | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr
列出所有连接到本机80端口的IP地址和其连接数。80端口一般是用来处理HTTP网页请求。

#netstat -plan|grep :80|awk {'print $5'}|cut -d: -f 1|sort|uniq -c|sort -nk 1
显示连接80 端口前10的ip,并显示每个IP的连接数。这里的80端口是http端口,所以可以用来监控web服务。如果看到同一个IP有大量连接的话就可以判定单点流量攻击了。
#netstat -antp | awk '$4 ~ /:80$/ {print $4" "$5}' | awk '{print $2}'|awk -F : {'print $1'} | uniq -c | sort -nr | head -n 10

Linux 相关信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
lsb_release -a              # 查看操作系统版本https://liam.page/2016/11/06/Linux-Info-Cheatsheet/
head -n 1 /etc/issue # 查看操作系统版本
cat /proc/version # 查看操作系统内核信息
uname -a # 查看操作系统内核信息、CPU 信息
cat /proc/cpuinfo # 查看 CPU 信息
hostname # 查看计算机名字
env # 列出环境变量
lsmod # 列出加载的内核模块
uptime # 查看系统运行时间、负载、用户数量
cat /proc/loadavg # 查看系统负载
free -m # 查看物理内存和交换区的使用情况
grep MemTotal /proc/meminfo # 查看内存总量
grep MemFree /proc/meminfo # 查看空闲内存总量
df -h # 查看各分区使用情况
fdisk -l # 查看所有分区
swapon -s # 查看所有交换分区
hdparm -i /dev/hda # 查看 IDE 磁盘的参数
dmesg | grep IDE # 查看系统启动时 IDE 磁盘的状态
mount | column -t # 查看各分区的挂载状态
du -sh <目录名> # 查看指定目录的大小
ifconfig # 查看所有网络接口的属性
iptables -L # 查看 iptables 防火墙
route -n # 查看本机路由表
netstat -lntp # 查看所有监听端口
netstat -antp # 查看所有已建立的连接
netstat -s # 查看网络统计信息
w # 查看活动用户以及他们在做什么
who # 查看活动用户
id <用户名> # 查看用户的 ID、组信息
cut -d: -f1 /etc/passwd # 查看系统中所有用户
cut -d: -f1 /etc/group # 查看系统所有组


cat <filename> | sort | uniq -d # 只显示重复的行,每行只显示一次 交集
cat <filename> | sort | uniq -D # 只显示重复的行
cat <filename> | sort | uniq -i # 忽略大小写
cat <filename> | sort | uniq -u # 只显示只出现一次的行
cat <filename> | sort | uniq -c # 统计每行重复的次数
sort <file1> <file2> <file2> | uniq -u # 差集
sort <file1> <file2> | uniq -u # 对称差集
https://liam.page/2016/05/05/best-match-using-sort-and-uniq-to-do-set-operations/
sort <file1> <file2> | uniq -d # 交集
sort <file1> <file2> | uniq # 并集

反向代理以访问 Gist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
listen 80;
server_name gist.example.com;
access_log off;
resolver 8.8.8.8;
location / {
proxy_pass https://gist.github.com;
proxy_cache_valid 200 302 1h;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout invalid_header updating
http_500 http_502 http_503 http_504;
proxy_set_header Accept-Encoding "";
proxy_set_header Accept-Language "zh-CN";
proxy_set_header User-Agent $http_user_agent;
sub_filter https://gist-assets.github.com/ http://gist.example.com;
sub_filter https://gist.github.com/ http://gist.example.com;
sub_filter_once off;
}
}
访问 http://gist.example.com 就相当于访问了 https://gist.github.com。https://liam.page/2015/09/07/reverse-proxy-to-get-access-to-gist/

文件名大小写有问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
方案一:

删除旧文件,提交代码。
添加新文件,提交代码。
方案二:修改配置

git config core.ignorecase false
方案三:

$ git mv test.txt tmp.txt
$ git mv tmp.txt Test.txt
$ git commit -m "Renamed test.txt to Test.txt"

找出请求次数最多的前50个IP:

awk '{print $1}' /path/to/web-server-log/access.log | sort|uniq -c | sort -nr | head -n 50

paste 命令支持输入多个文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ paste -d '|' paste2.txt paste1.txt paste3.txt
a|1|A
b|2|B
c|3|C
$ who
Liam :0 2016-11-08 00:07
Liam pts/0 2016-11-08 00:23 (:0.0)
Liam pts/1 2016-11-08 00:15 (:0.0)
$ who | tr -s ' '
Liam :0 2016-11-08 00:07
Liam pts/0 2016-11-08 00:23 (:0.0)
Liam pts/1 2016-11-08 00:15 (:0.0)
使用 -s 参数,可以逐行地将连续的字符 unique 成单独的一个字符。
$ who | tr -s ' ' | cut -d ' ' -f 1,3,4
Liam 2016-11-08 00:07
Liam 2016-11-08 00:23
Liam 2016-11-08 00:15

Git webhook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//http://blog.text.wiki/2017/10/31/git-webhooks-for-php.html
设置用于接收请求的 URL。
服务器收到 push、pull request、merge、tag 等操作时,会将相应信息发送给步骤 1 里的 URL。
URL 对应的程序收到网络请求后,执行自动部署、邮件通知等操作。

部署 SSH 无密码登录 GitHub 为例,在 Settings -> Deploy keys,选择 Add deploy key.

<?php
$raw_data = file_get_contents("php://input");
$pay_load = json_decode($raw_data,true);
//监测请求来源合法性,
if($pay_load['password'] != 'pass'){
exit('ok 400');
}
//检查是否为master分支
if($pay_load["ref"] != "refs/heads/master"){
exit('ok 401');
}

exec('sh /var/www/hooks/build.sh');

#! /bin/bash
SITE_PATH='/var/www/weixinbook'
USER='www-data'
USERGROUP='www-data'
cd $SITE_PATH
git reset --hard origin/master
git clean -f
git pull
git checkout master
chown -R $USER:$USERGROUP $SITE_PATH

删除某个文件的所有历史记录

1
2
3
$ git filter-branch -f --tree-filter 'rm -rf common/service/SyncBlogServince.php' HEAD
$ git push origin --force
http://www.54php.cn/default/90.html

批量kill进程

1
ps -ef|grep 'python' |grep -v grep| awk '{print $2}’ | xargs kill -9

nginx日志按日期切割并保留最近七天的日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
## 零点执行该脚本https://www.einsition.com/article/5/details

## Nginx 日志文件所在的目录
LOGS_PATH="/www/log/nginx"

mkdir -p ${LOGS_PATH}/backup/

mv ${LOGS_PATH}/api.einsition.com-access.log ${LOGS_PATH}/backup/api.einsition.com-access_$(date -d "yesterday" +"%Y%m%d").log
mv ${LOGS_PATH}/api.einsition.com-error.log ${LOGS_PATH}/backup/api.einsition.com-error_$(date -d "yesterday" +"%Y%m%d").log

## 向 Nginx 主进程发送 USR1 信号。USR1 信号是重新打开日志文件
# nginx_pid=`ps -ef |grep -v grep |grep "nginx: master process"|awk -F" " '{print $2}'`
# kill -USR1 $nginx_pid
kill -USR1 $(cat /run/nginx.pid)

cd ${LOGS_PATH}/backup/
find . -name "*.einsition.com*.log" -type f -mtime +7 -exec rm -f {} \;

检测端口是否打开

1
2
3
4
5
6
7
8
9
10
11
12
yum install -y nc
[root@su html]# nc -v www.buyao.bid 5050
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 38.143.1.156:5050.
[root@su html]# nc -v baidu.com 8123
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connection to 123.125.115.110 failed: Connection timed out.
Ncat: Trying next address...

[root@su html]# nc -v baidu.com 443
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 123.125.115.110:443.

Composer 设置忽略版本匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
vagrant@homestead:/usr/share/nginx/html/laravel-blog$ sudo composer install
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Installation request for doctrine/instantiator 1.0.3 -> satisfiable by doctrine/instantiator[1.0.3].
- doctrine/instantiator 1.0.3 requires php ~5.3 -> your PHP version (7.0.3) does not satisfy that requirement.
Problem 2
- doctrine/instantiator 1.0.3 requires php ~5.3 -> your PHP version (7.0.3) does not satisfy that requirement.
- phpunit/phpunit-mock-objects 2.3.0 requires doctrine/instantiator ~1.0,>=1.0.1 -> satisfiable by doctrine/instantiator[1.0.3].
- Installation request for phpunit/phpunit-mock-objects 2.3.0 -> satisfiable by phpunit/phpunit-mock-objects[2.3.0].
提示我的PHP 7版本太高,不符合composer.json需要的版本,但是在PHP 7下应该也是可以运行的,composer可以设置忽略版本匹配,命令是:

解决方案https://blog.fastrun.cn/2016/05/05/1-24/
composer install --ignore-platform-reqs
or

composer update --ignore-platform-reqs

linux

1
2
3
4
5
6
7
8
9
10
11
12
13
统计 IP 连接数
$ netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10

# 当前用户
$ whoami
root
# 当前所有用户
$ ps -ef | grep 'pts'
root 4752 4727 0 00:09 pts/0 00:00:00 su www
www 4755 4752 0 00:09 pts/0 00:00:00 bash
剔除非法登陆用户:https://www.fanhaobai.com/2018/01/linux-skill.html

$ kill -9 4755

深入 Nginx 之配置篇

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
user admin; #配置用户或者组。

worker_processes 4; #允许生成的进程数,默认为1

pid /nginx/pid/nginx.pid; #指定 nginx 进程运行文件存放地址

error_log log/error.log debug; #错误日志路径,级别。
http {
include mime.types; #文件扩展名与文件类型映射表

default_type application/octet-stream; #默认文件类型,默认为text/plain

access_log off; #取消服务日志

sendfile on; #允许 sendfile 方式传输文件,默认为off,可以在http块,server块,location块。

sendfile_max_chunk 100k; #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。

keepalive_timeout 65; #连接超时时间,默认为75s,可以在http,server,location块。

server
{
keepalive_requests 120; #单连接请求上限次数。

listen 80; #监听端口

server_name 127.0.0.1; #监听地址

index index.html index.htm index.php;

root your_path; #根目录

location ~ \.php$
{
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;

#fastcgi_pass 127.0.0.1:9000;

fastcgi_index index.php;

include fastcgi_params;
}

}
}upstream test-upstream {
ip_hash; # 使用 ip_hash 算法分配 https://learnku.com/articles/24795#topnav

server 192.168.1.1; # 要分配的 ip
server 192.168.1.2;
}

server {

location / {
proxy_pass http://test-upstream;
}

}

nginx日志中提取5分钟内访问状态非200的记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
nginx部分访问日志如下:

100.0.0.16 - - [27/Aug/2015:10:44:58 +0000] GET www HTTP/1.120015 “-” “-” “-” “3.254” “192.168.1.1:80

100.0.1.13 - - [27/Aug/2015:10:45:22 +0000] GET www HTTP/1.120090 “-” “-” “-” “0.498” “192.168.1.1:80

100.0.1.13 - - [27/Aug/2015:10:46:26 +0000] GET www HTTP/1.120090 “-” “-” “-” “1.704” “192.168.1.1:80

100.0.1.16 - - [27/Aug/2015:10:46:35 +0000] GET www HTTP/1.120094 “-” “-” “-” “1.189” “192.168.1.1:80

采用awk多分隔符实现
awk -F'[/ "]' '$6>="2015:10:44:00" && $6<="2015:10:49:00" && $13 != 200'

分析2015/8/152015/8/16 访问"/index.php?g=Member&m=Public&a=sendValidCode"的IP倒序排列

cat log_file | egrep '15/Aug/2015|16/Aug/2015' | awk '{if($7 == "/index.php?g=Member&m=Public&a=sendValidCode") print $1,$7}'|sort|uniq -c|sort -nr

golang入门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
var b []int
numbers := make([]int,5,10)
// 创建切片
number2 := make([]int, 15)
// 将原始切片复制到新切片
copy(number2, number)

// 初始化长度为 4,以及赋值
number2 := []int{1,2,3,4}
fmt.Println(numbers) // -> [1 2 3 4]
// 创建子切片
slice1 := number2[2:]
fmt.Println(slice1) // -> [3 4]
slice2 := number2[:3]
fmt.Println(slice2) // -> [1 2 3]
slice3 := number2[1:4]
fmt.Println(slice3) // -> [2 3 4]
if num := 9; num < 0 {
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit")
} else {
fmt.Println(num, "has multiple digits")
}
var ap *int ap 是指向整数类型的指针。& 运算符可用于获取变量的地址。

a := 12
ap = &a
可以使用 * 运算符访问指针指向的值:

fmt.Println(*ap)
// => 12
func increment(i *int) {
*i++
}
func main() {
i := 10
increment(&i)
fmt.Println(i)
}
//=> 11
func add(a int, b int) int {
c := a + b
return c
}
func add(a int, b int) (c int) {
c = a + b
return
}
func add(a int, b int) (int, string) {
c := a + b
return c, "successfully added"
}
type person struct {
name string
age int
gender string
}
//方式1:指定属性和值
p = person{name: "Bob", age: 42, gender: "Male"}
//方式2:指定值
person{"Bob", 42, "Male"}
p.name
//=> Bob

pp = &person{name: "Bob", age: 42, gender: "Male"}
pp.name
//=> Bob

//定义结构体
type person struct {
name string
age int
gender string
}

// 方法定义
func (p *person) describe() {
fmt.Printf("%v is %v years old.", p.name, p.age)
}
func (p *person) setAge(age int) {
p.age = age
}

func (p person) setName(name string) {
p.name = name
}

func main() {
pp := &person{name: "Bob", age: 42, gender: "Male"}
pp.describe()
// => Bob is 42 years old
pp.setAge(45)
fmt.Println(pp.age)
//=> 45
pp.setName("Hari")
fmt.Println(pp.name)
//=> Bob
}
Go 的接口是一系列方法的集合。接口有助于将类型的属性组合在一起 结构体是不同字段的类型集合。 结构用于将数据分组在一起。
type animal interface {
description() string
}
type cat struct {
Type string
Sound string
}

type snake struct {
Type string
Poisonous bool
}

func (s snake) description() string {
return fmt.Sprintf("Poisonous: %v", s.Poisonous)
}

func (c cat) description() string {
return fmt.Sprintf("Sound: %v", c.Sound)
}

func main() {
var a animal
a = snake{Poisonous: true}
fmt.Println(a.description())
a = cat{Sound: "Meow!!!"}
fmt.Println(a.description())
}
godoc person Description
它将会为我们的 person 包内部的 Description 函数生成文档。查看文档的话只需要使用如下命令启动一个 web 服务器就可以:

godoc -http=":8080"
现在去访问这个 URL http://localhost:8080/pkg/ 然后你就可以看到我们刚创建的包文档了。
func main(){
resp, err := http.Get("http://example.com/")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(resp)
}
https://learnku.com/golang/t/24715#reply83037

linux chmod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

777 --- 代表所有人都有最高权限
755 --- 执行文件的常用权限
644 --- 普通文件的常用权限
关于为什么有文件的写权限,却不能删除文件的问题解释

对于某个目录或文件拥有的w权限,针对的是里面的内容,而不是文件本身

由此,对文件的删除是对文件所在目录的写,故必须有目录的写权限才可以
对文件来讲: 最高权限是 x(执行)
对目录来讲: 最高权限是 w(写)具有修改目录结构的权限。如新建文件和目录,删除此目录下文件和目录,重命名此目录下文件和目录,剪切

针对目录
755是最常用的权限设定方式,(目录所有者可以删除和创建目录下文件,其他人只能进入看看)

稍微严谨一点是750,其他人进都进不来

极端严谨一点是700,就我自己能进能看能改,其他所有拒之门外
针对普通文件
644是最常用的权限设定方式,(文件所有者能看能改,其他人只能看)

640是其他人不能看不能改

600是其他所有人不能看不能改
针对可执行文件
754是最常用的权限设定方式,(文件所有者可以看改执行,组内可以执行,其他人只能看)

750740700都是可以的
还有一点
文件所有者必须为7或者是6,要不就是傻逼 https://learnku.com/articles/22095#topnav

通过 kill ps -ef | grep 'ddd' https://learnku.com/articles/21339#topnav

这种形式,这个时候实际上等同于拼接字符串得到的命令,其效果类似于 kill $pid
for procid in $(ps -aux | grep "some search" | awk '{print $2}'); do kill -9 $procid; done

其实与第一种原理一样,只不过需要多次kill的时候是循环处理的,每次处理一个
ps -ef | grep 'ddd' | xargs kill
echo '11@22@33@44@55@66@77@88@99@00' | xargs -d '@' -n 3 echo
输出结果:

11 22 33
44 55 66
77 88 99
00
find的输出结果是每条记录后面加上换行,也就是每条记录是一个新行
find . -name "*.txt" -print0
输出:

./2.txt./3.txt./1.txt => 加上 -print0 参数表示find输出的每条结果后面加上 '\0' 而不是换行
find . -name "*.txt" -print0 | xargs -0 echo
输出:

./2.txt ./3.txt ./1.txt

nginx 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
禁止空主机头和未授权域名访问
$ vim conf.d/default.conf
server {
listen 80 default;
server_name _;
return 500;
}
$ vim vhosts/blog.yiranzai.cn.conf
server {
listen 80;
server_name blog.yiranzai.cn;
location / {
proxy_pass http://127.0.0.1:88;
include /etc/nginx/proxy.conf; #代理配置
}
}
$ vim proxy.conf
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
$ firewall-cmd --zone=public --add-port=80/tcp --permanent
success
$ firewall-cmd --reload
success
systemctl start nginx.service #启动nginx
systemctl enable nginx.service #将nginx开机启动
systemctl stop nginx.service #停止nginx服务
systemctl reload nginx.service #重新加载nginx配置(推荐)
systemctl restart nginx.service #重启nginx服务(不推荐,会关闭所有进程)

php-fpm
fastcgi_finish_request() - 特殊功能:用于在请求完成和刷新数据后,继续在后台执行耗时的工作(录入视频转换、统计处理等);

svn搭建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
yum install -y subversion

$ mkdir /var/www/svn
$ cd /var/www/svn
$ svnadmin create /var/www/svn
$ ls
conf db format hooks locks README.txt
$ vim conf/passwd
[users]
# harry = harryssecret
# 账号 = 密码
svn = svnpasswd
svnre = svnrepasswd
$ vim conf/authz
[/] //仓库下所有文件
svn=rw //可读可写
svnre=r //只读
*= //其他用户无任何权限$ vim conf/svnserve.conf

anon-access = read #匿名用户可读
auth-access = write #授权用户可写
password-db = passwd #使用哪个文件作为账号文件
authz-db = authz #使用哪个文件作为权限文件
realm = /var/www/svn/ # 认证空间名,版本库所在目录
$ svnserve -d -r /var/www/svn //-d 表示守护进程, -r 表示在后台执行,默认端口为3690
$ svnserve -d -r --listen-port 3691 /var/www/svn //指定3691端口启动该服务
$ killall svnserve //停止全部
$ ps -ef | grep svnserve
root 4148 1 0 Dec12 ? 00:00:00 svnserve -d -r /var/www/svn/a/
root 8995 1 0 Dec09 ? 00:00:00 svnserve -d -r /var/www/svn/b/ --listen-port 3691
root 14855 1 0 Dec19 ? 00:00:00 svnserve -d -r /var/www/svn/c/ --listen-port 3692
root 27538 27343 0 09:39 pts/0 00:00:00 grep --color=auto svnserve
$ kill 8995 //停止3692端口的svnserve
windows中使用TortoiseSVN连接,输入地址 svn://118.24.158.116/ 即可,不出意外输入用户名svn和密码svnrepasswd就能连接成功了。
默认端口3690,如果你修改了端口,那么要记得加上端口号。

Git 钩子检查 PHP 语法和代码规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/bin/bash
#
# (c) Copyright codcodog
#
# PHP 语法检查以及代码规范检查 https://github.com/codcodog/phpconfig/blob/master/git/pre-commit
#如果该钩子以非零值退出,Git 将放弃此次提交,不过你可以用 git commit --no-verify 来绕过这个环节
# 依赖:
# - php-cs-fixer
# - php-parallel-lint

set -e

PHP='php'
CODE_STYLE_CHECK='vendor/bin/php-cs-fixer fix --dry-run --diff --diff-format=udiff -vvv'
CODE_SYNTAX_CHECK='vendor/bin/parallel-lint -j 10'

files=$(git diff --cached --name-only)

# 若 host 没有安装 PHP
# 则使用 docker 环境的 PHP
is_docker_php()
{
if ! command -v $PHP > /dev/null 2>&1; then
PHP='docker exec php php'
CODE_STYLE_CHECK="$PHP $CODE_STYLE_CHECK"
CODE_SYNTAX_CHECK="$PHP $CODE_SYNTAX_CHECK"
fi
}

is_php()
{
file_extension="${1##*.}"
if [[ "$file_extension" == 'php' ]]; then
return 0
fi

return 1
}

check_syntax()
{
if ! $CODE_SYNTAX_CHECK "$1" > /dev/null 2>&1; then
$CODE_SYNTAX_CHECK "$1"
exit 1
fi
}

check_style()
{
if ! $CODE_STYLE_CHECK "$1" > /dev/null 2>&1; then
$CODE_STYLE_CHECK "$1"
exit 1
fi
}

main()
{
is_docker_php
for f in $files; do
if is_php "$f"; then
check_syntax "$f"
check_style "$f"
fi
done
}

main
exit 0

带宽被打满

1
2
3
4
5
apt-get install iftop
根据阿里云的监控面板是网卡1(eth1)流量异常,所以通过 iftop 工具监控下 eth1 的流量:
https://laravelacademy.org/post/9838.html
iftop -i eth1 -P // 带 -P 显示对应端口号
iptables -I INPUT -s 114.84.146.45 -j DROP

你可能会忽略的 Git 提交规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<type>(<scope>): <subject>
type
用于说明 commit 的类别,只允许使用下面7个标识。https://learnku.com/articles/25456#topnav

feat:新功能(feature)
fix:修补bug
docs:文档(documentation)
style: 格式(不影响代码运行的变动)
refactor:重构(即不是新增功能,也不是修改bug的代码变动)
test:增加测试
chore:构建过程或辅助工具的变动
scope

用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。
subject

是 commit 目的的简短描述,不超过50个字符。
以动词开头,使用第一人称现在时,比如change,而不是changed或changes
第一个字母小写
结尾不加句号(.)
Commit 规范的作用

1、提供更多的信息,方便排查与回退;
2、过滤关键字,迅速定位;
3、方便生成文档;
npm install -g conventional-changelog
cd jartto-domo
conventional-changelog -p angular -i CHANGELOG.md -w
为了方便使用,可以将其写入 package.json 的 scripts 字段。

{
"scripts": {
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -w -r 0"
}
}
这样,使用起来就很简单了:https://www.conventionalcommits.org/zh/v1.0.0-beta.3/

npm run changelog
npm install --save-dev validate-commit-msg

git pull或git checkout 后保持权限不变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
https://www.guaosi.com/2018/12/06/git-auto-change/
服务器上的项目,一般都是使用用户组www-data或者www来保证权限安全,不会使用root的。但是git pull下来的新文件或者修改的文件,则会把原有的文件的权限更改为644,用户组改为root

chmod -R 755 www.guaosi.com/
# 修改项目内所有文件为755权限
chown -R www-data:www-data www.guaosi.com/
# 修改项目内所有文件的用户和用户组为www-data

cd .git/hooks/
vim post-merge
#!/bin/sh
pwd
echo "This is post-merge hook"
chmod -R 755 ./* && chown -R www-data:www-data ./*
chmod +x post-merge
vim post-checkout
#!/bin/sh
pwd
echo "This is post-checkout hook"
chmod -R 755 ./* && chown -R www-data:www-data ./*

chmod +x post-checkout

Git 仓库迁移至其他服务器并实现 hooks 自动化部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//https://learnku.com/articles/26130
一:git仓库迁移

1.把需要迁移的项目克隆一份至本地电脑上。

//从原地址克隆一份裸版本库,比如原本托管在旧服务器的私有仓库
//–bare 创建的克隆版本库都不包含工作区,直接就是版本库的内容,这样的版本库称为裸版本库。
git clone --bare ssh://git@192.10.0.1/home/git/test.git
2.到新的 Git 服务器上创建一个新项目。

//切换git用户,没有需要创建git用户
su - git
//进入git家目录
cd /home/git
//创建项目
mkdir test.git
//初始化一个裸仓库
git init --bare test.git
3.切换到本地电脑,以镜像推送的方式上传代码到新的服务器上。

//进入第一步复制下来的test.git 项目
cd test.git
//以镜像推送的方式上传代码到新的服务器上。
//请确保已经添加了公钥到新的机器上
git push --mirror ssh://git@192.10.0.2/home/git/test.git
4.删除本地电脑的test.git 项目。

//rm -rf test.git
5.从新的git仓库中clone项目到本地。

git clone ssh://git@192.10.0.2/home/git/test.git
至此,git项目完整的迁移到了新的服务器上。
二 hooks自动部署到网站根目录

1.把项目clone至本地根目录

cd /var/www/html //进入网站上级目录
git clone /home/git/test.git //test克隆test.git仓库到test网站根目录
chmod -R 777 test //给网站根目录设置权限
chown -R git:git test //将git用户权限设置到test根目录上
2.设置钩子

cd /home/git/test.git/hooks/
vim post-receive
//将以下内容写入到 post-receive中,并给post-receive设置可读写权限

#!/bin/bash
IS_BARE=$(git rev-parse --is-bare-repository)
if [ -z "$IS_BARE" ]; then
echo >&2 "fatal: post-receive: IS_NOT_BARE"
exit 1
fi
unset GIT_DIR
DeployPath="/var/www/html/test" //你的网站根目录
cd $DeployPath
git fetch --all
git reset --hard origin/master

更新与回滚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ cd /var/www/deployment
$ git remote set-url origin 'git@github.com:wi1dcard/hello-deployment.git'
git fetch 命令获取远端状态(但不拉取到本地):

$ git fetch -t -v
穿越到远端 master 分支的倒数第一次提交(即最新提交),通常用于更新至最新代码。

$ git reset --hard origin/master
穿越到远端 master 分支倒数第三次提交,通常用于回滚一部分错误提交。

$ git reset --hard origin/master~2
穿越到 ID 为 602fa83 的提交,通常用于回滚到特定版本。

$ git reset --hard 602fa83

切换账号执行脚本

1
2
3
4
5
6
7
8
function install_composer {
# 「⚠️重点」下载 Composer 的 PHAR 文件https://learnku.com/articles/24919#topnav
wget https://dl.laravel-china.org/composer.phar -O /usr/local/bin/composer
# 「⚠️重点」给予该文件可执行权限
chmod +x /usr/local/bin/composer
# 配置 Packagist 国内镜像
sudo -H -u ${WWW_USER} sh -c 'cd ~ && composer config -g repo.packagist composer https://packagist.laravel-china.org'
}

生成压缩包

1
2
3
对mster分支代码生成压缩包供使用者下载使用,--prefix 指定目录名

git archive master --prefix='hdcms/' --format=zip > hdcms.zip

自动部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
GitHub设置 WebHook
<?php
// GitHub Webhook Secret.
// GitHub项目 Settings/Webhooks 中的 Secret
$secret = "houdunren";

// Path to your respostory on your server.
// e.g. "/var/www/respostory"
// 项目地址 https://www.houdunren.com/document/front/content/158?sid=1&mid=2
$path = "/www/wwwroot/xj.houdunren.com";

// Headers deliveried from GitHub
$signature = $_SERVER['HTTP_X_HUB_SIGNATURE'];

if ($signature) {
$hash = "sha1=".hash_hmac('sha1', file_get_contents("php://input"), $secret);
if (strcmp($signature, $hash) == 0) {
echo shell_exec("cd {$path} && /usr/bin/git reset --hard origin/master && /usr/bin/git clean -f && /usr/bin/git pull 2>&1");
exit();
}
}

http_response_code(404);

chown -R www .
chmod -R g+s .
sudo -u www git pull

CONFLICT (modify/delete)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ git merge wechat_login
CONFLICT (modify/delete): Wechat.php deleted in HEAD and modified in wechat_login. Version wechat_login of Wechat.php left in tree.
Automatic merge failed; fix conflicts and then commit the result.

$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)

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

deleted by us: Wechat.php
https://www.jianshu.com/p/b08316888124

Already up-to-date

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
先切换到master分支,再执行git checkout master
git merge dev复制代码若合并分支时提示“Already up-to-date”在使用Git把当前分支合并到master提示“Already up-to-date”,但当前分支和 master 分支代码不同步。
假设当前分支是:dev,主分支是:master。
解决方法:git checkout master;
git reset --hard dev;
git push --force origin master
$ git merge test
Already up to date.

$ git status
On branch master
nothing to commit, working tree clean

$ git diff test app/Http/Controllers/Test.php
diff --git a/app/Http/Controllers/Test.php b/app/Http/Controllers/Test.php
index 27c8be83..c40f563f 100644
--- a/app/Http/Controllers/Test.php
+++ b/app/Http/Controllers/Test.php
@@ -55,7 +55,6 @@ class Test extends Controller {

- $return['data'] = $app ? $app['result'] : [];


}

https://juejin.im/post/5c3d5f40f265da6169177506

文件名大小写修改

1
2
3
4
5
先复制文件,再修改
cp Abc.sh bbc.sh
svn del Abc.sh
mv bbc.sh abc.sh
svn add abc.sh

ssh公私钥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
第一步,在客户端生成公钥

ssh-keygen -t rsa #生成的公钥匙在 ~/.ssh/ 目录下
第二步,把公钥上传到服务器端,登录服务器追加公钥到 authorized_keys 文件

简单版

ssh-copy-id -i ~/.ssh/id_rsa.pub username@ip
复杂版

scp id_rsa.pub root@ip地址:文件保存路径
ssh root@ip #登录服务器
cd id_rsa.pub 文件保存路径
cat id_rsa.pub >> /root/.ssh/authorized_keys 追加到文件中
如果 .shh 目录或 authorized_keys 文件不存在需要自己新建

第三步,修改服务器端 ssh 配置文件 /etc/ssh/sshd_config

RSAAuthentication yes #开启RSA验证
PubkeyAuthentication yes #是否使用公钥验证
PasswordAuthentication no #禁止使用密码验证登录
chmod 700 /root/.ssh/ #为了安全把文件修改权限,可选,部分系统新建即为 700
chmod 600 /root/.ssh/authorized_keys #为了安全把文件修改权限,可选,部分系统新建即为 600
第四步,服务器端重启 ssh 服务

service sshd restart #重启 sshd 服务

在 .ssh 目录下新建 config 文件,内容如下

Host test1 #自定义名称
HostName ip #服务器 ip 地址
User nick #用户名
Port 22 # ssh 端口号,默认 22 可以不设置

Host test2 #自定义名称
HostName ip #服务器 ip 地址
User nick #用户名
Port 22228 # ssh 端口,自定义端口,修改为指定端口号
连接方式

ssh test1 #如果配置了公私钥就直接登录,没有的话输入密码登录 https://linux.hellocode.name/used-settings.html

Connection reset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37




ssh: connect to host github.com port 22: Connection timed out
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

说明git软件无法通过ssh连接到github,有可能时防火墙或ISP设置的防火墙阻止端口22上的ssh连接,可以用以下命令替换:
git remote add origin-https xxx(https方式)
git push -u origin-https master
git pull origin-https master

$ git config --local -l
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true
remote.github.url=git@sushengbuhuo.github.com:sushengbuhuo/sushengbuhuo.github.io.git
remote.github.fetch=+refs/heads/backup:refs/remotes/github/backup
branch.master.remote=github
branch.master.merge=refs/heads/backup

运行git config --local -e打开配置信息。
修改其中的


url = git@github.com:username/repo.git



url = https://username@github.com/username/repo.git
这样就改为使用https协议了。提交什么的就OK了。

Could not read from remote repository

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
$ git clone git@xxx.com/app/api.git
Cloning into 'api'...
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
The ECDSA host key for git.staff.sina.com.cn has changed,
and the key for the corresponding IP address
is unknown. This could either mean that
DNS SPOOFING is happening or the IP address for the host
and its host key have changed at the same time.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:q5enZT9xuv1ySs09+ .
Please contact your system administrator.
Add correct host key in /c/Users/xxx/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /c/Users/xxx/.ssh/known_hosts:8
ECDSA host key for git.xxx.com has changed and you have requested strict checking.
Host key verification failed.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

删除/c/Users/xxx/.ssh/known_hosts 第8行重新clone
git clone git@xxx.com/app/api.git
Cloning into 'api'...
The authenticity of host 'git.xxx.com ' can't be established.
ECDSA key fingerprint is SHA256:q5enZT9xuv1ySs09+ .
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'git.xxx.com, ' (ECDSA) to the list of known hosts.
remote: Enumerating objects: 63303, done.
remote: Counting objects: 100% (63303/63303), done.
remote: Compressing objects: 100% (19487/19487), done.
remote: Total 63303 (delta 42781), reused 62710 (delta 42523)
Receiving objects: 100% (63303/63303), 23.86 MiB | 14.71 MiB/s, done.
Resolving deltas: 100% (42781/42781), done.
Checking out files: 100% (9761/9761), done.

Git 优雅的撤销中间某次提交

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
git revert 100047dcc -m 1
参数 -m 就是指定要撤销的那个提价,从左往右,从 1 开始数;也就是我撤销的是 0099aca7。
接着其把代码冲突,然后我就解决冲突,保留主分支的代码,去掉那个人的代码。
git push

1,首先git log查看提交记录,找到出错的前一笔提交的commit_id

2,用命令git rebase -i commit_id ,查找提交记录

3,将出错那笔提交的pick改为drop

4,Esc,:wq

1、git reset --hard 1d7444 #回退到出错版本前一个commit

2、git cherry-pick 626335 #将某次commit的更改应用到当前版本(将出错 cmmit 之后别人提交的代码合并到当前正常代码分支上)

3、git push origin HEAD --force #强制提交
https://learnku.com/articles/31705

git原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
创建 blob 对象:

$ echo 'test content' | git hash-object -w --stdin

-w 表示存储对象。

d670460b4b4aece5915caf5c68d12f560a9fe3e

返回一个长度为 40 字符的校验和,为对象名。校验和是一个 SHA-1 哈希值,由对象数据和一个 header 一起做 SHA-1 校验运算而成。

读取 blod 对象

$ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e

test content

-p Pretty-print the contents of object based on its type.

-t 输出对象类型

blob
HEAD 引用

用途:记录当前分支所在的分支引用

存储当前分支的引用的引用,是一个符号引用,不像普通引用包含一个 SHA-1 值。

$ cat .git/HEAD

ref: refs/heads/test
cat .git/refs/heads/master
4b8c160d38e4befa3bc515f12208583dd4e8814f

$ cat .git/refs/remotes/origin/master

4b8c160d38e4befa3bc515f12208583dd4e8814f

git cat-file -p 4b8c160d38e4befa3bc515f12208583dd4e8814f

tree 40db0fc4e10857c0a774365c799ffd7e2fe4c052
parent cb65f329f7928a39e801af5151539246a70dfea6
parent ae4107d8e7eb6dec926f2488c70dab23a06bc9d8
author 666 1565317494 +0800
committer 66 1565317494 +0800

Merge branch 'feature/test'
https://learnku.com/articles/32272

Git 获取指定文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
https://me.jinchuang.org/archives/145.html
具体实现如下:
$mkdir project_folder
$cd project_folder
$git init
$git remote add -f origin <url>
上面的代码会帮助你创建一个空的本地仓库,同时将远程Git Server URL加入到Git Config文件中。
接下来,我们在Config中允许使用Sparse Checkout模式:
$git config core.sparsecheckout true
接下来你需要告诉Git哪些文件或者文件夹是你真正想Check Out的,你可以将它们作为一个列表保存在.git/info/sparse-checkout文件中。
例如:
$echo “libs” >> .git/info/sparse-checkout
$echo “apps/register.go” >> .git/info/sparse-checkout
$echo “resource/css” >> .git/info/sparse-checkout
最后,你只要以正常方式从你想要的分支中将你的项目拉下来就可以了:
$git pull origin master

Git 实现 Laravel 项目的自动化部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 创建一个名叫jouzeyu的用户
adduser jouzeyu
#在根目录下的 home 文件夹下创建一个git文件夹
mkdir /home/git
#切换到创建好的git文件夹
cd /home/git
#创建 .ssh文件夹,里面主要用来放公钥
mkdir .ssh
#切换到.ssh文件夹并创建authorized_keys文件
cd .ssh
touch authorized_keys

使用 cat ~/.ssh/id_rsa.pub 命令可以获取公钥,复制它,使用 vi 或者 vim 命令把它粘贴到我们之前创建的 authorized_keys 文件中,使用:wq 保存

mkdir /www/wwwroot/git
cd /www/wwwroot/git
初始化仓库:

#初始化一个裸仓库(强烈建议)
git init --bare website.git
#配置仓库的权限,让我们之前创建好的git用户jouzeyu能读写
chown -R git:git website.git


#创建我服务器上的项目目录test
mkdir /www/wwwroot/test
#克隆仓库
git clone /www/wwwroot/git/website.git
#设置权限
chown -R git website

# 通过ip地址从配置好的线上仓库拉取下来
git clone git@47.97.121.XXX:/www/wwwroot/git/website.git
# 如果有配置域名的话也可以通过域名拉取
git clone git@www.XXX.XXX:/www/wwwroot/git/website.git

# 打开刚才克隆下来的本地仓库
cd website
# 创建README.md文件
touch README.md
git add .
git commit -m"创建README.md文件"
git push

#切换到这个目录
cd /www/wwwroot/git/website.git/hooks
# 生成post-receive文件
touch post-receive
# 使用vim编辑
vim post-receive

#!/bin/sh
# 打印输出
echo '======上传代码到服务器======'
# 打开线上项目文件夹
cd /www/wwwroot/test/website
# 这个很重要,如果不取消的话将不能在cd的路径上进行git操作
unset GIT_DIR
git pull origin master
# 自动编译vue项目,如有需要请去掉前面的#号
# npm run build
# 自动更新composer(我暂时没试过)
# composer update
echo $(date) >> hook.log
echo '======代码更新完成======'

chmod +x post-receive
https://learnku.com/articles/33689

gitee 和 GitHub 的 webhook 的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//访问秘钥
$keySecret = '^!@KVzPZ^DaRNA7R53353%7aEAfsfdOptH7b%0i5';

//需要更新的项目目录
$wwwRoot = [
'/www/wwwroot/test1',
'/www/wwwroot/test2',
];

//保存运行脚本的日志
$logFile = 'log/layuimini-githook.log';

//git执行命令
$gitCommand = 'git pull';

// 判断是否开启秘钥认证(已实现gitee和github)
if (isset($keySecret) && !empty($keySecret)) {
list($headers, $gitType) = [[], null];
foreach ($_SERVER as $key => $value) {
'HTTP_' == substr($key, 0, 5) && $headers[str_replace('_', '-', substr($key, 5))] = $value;
if (empty($gitType) && strpos($key, 'GITEE') !== false) {
$gitType = 'GITEE';
}
if (empty($gitType) && strpos($key, 'GITHUB') !== false) {
$gitType = 'GITHUB';
}
}
if ($gitType == 'GITEE') {
if (!isset($headers['X-GITEE-TOKEN']) || $headers['X-GITEE-TOKEN'] != $keySecret) {
die('GITEE - 请求失败,秘钥有误');
}
} elseif ($gitType == 'GITHUB') {
$json_content = file_get_contents('php://input');
$signature = "sha1=" . hash_hmac('sha1', $json_content, $keySecret);
if ($signature != $headers['X-HUB-SIGNATURE']) {
die('GITHUB - 请求失败,秘钥有误');
}
} else {
die('请求错误,未知git类型');
}
}

!is_array($wwwRoot) && $wwwRoot = [$wwwRoot];
foreach ($wwwRoot as $vo) {
$shell = sprintf("cd %s && git pull 2>&1", $vo);
$output = shell_exec($shell);
$log = sprintf("[%s] %s \n", date('Y-m-d H:i:s', time()) . ' - ' . $vo, $output);
echo $log;
file_put_contents($logFile, $log, FILE_APPEND);
}
修改项目目录权限 chown -R www:www 项目路径

Forestry 管理基于 GitHub 的图床

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
免费提供静态博客管理功能,使你的博客拥有 CMS 般的体验。
你可以很轻松地编写、修改和发布博客,包括图片与文件,而不需要手动去编译上传,Forestry 已经为你自动处理了
github登录https://forestry.io/

授权对应的GitHub库

修改时区

Settings >> General >> TIMEZONE,选择 (GMT+08:00) Beijing,保存 Save settings

修改上传规则

Settings >> Media >> UPLOAD DIRECTORY 改为空
Settings >> Media >> PUBLIC PATH 改为空
Settings >> Media >> FILE PATH 改为 :year::month::day:/:filename:

本地上传文件 在GitHub可以看到
图片地址 https://cdn.jsdelivr.net/gh/sushengbuhuo/pics@master/20191022/钟楚红.jpg

https://gleehub.com/other/shi-yong-forestry-guan-li-ji-yu-github-de-tu-chuang.html
使用jsDelivr加速Github仓库的图片作为博客的图床 https://tingtas.com/posts/4341d485/#前言

删除git历史

1
2
3
4
5
6
7
8
git checkout --orphan new
git add -A
git commit -m "init"
git branch -D master

git branch -m new master
git push --set-upstream origin master -f
https://juejin.im/post/5be995c25188250fa8358f9d

Linux 环境下 Git 服务器的搭建

Git 命令行辅助脚本工具

GitHub Pages 指南极客学院

git简化笔记

Git笔记(三)——[cherry-pick, merge, rebase]

跟我一起学Git(十二) 合并项目

GIT使用rebase和merge的正确姿势

Github 的 WebHooks 实现代码自动更新

GitHub搜索

随机删文件

Github 项目活跃度分析工具

浏览 GitHub 问题和提取请求的方法

github 图解教程

在Windows安装Gogs

svn安装和使用总结

随机生成 Git commit git commit -m $(curl -s http://whatthecommit.com/index.txt)

CentOS 7 | Firewall防火墙使用总结

基于Gitea打造一个属于你自己的代码托管平台

基于 Gitea+Drone CI+Vault 打造属于自己的CI/CD工作流

Git 练习场–直观形象又好玩

linux从入门到实践

nginx从入门到实践

在 Linux 下搭建 Git 服务器

学习git

学好英语,走向国际

Mac/Linux 安装中文版 man 帮助命令

PHP、Git、Shell等笔记

netstat 命令查看连接数判断攻击

在Github上建立自己的Wiki

Git的各种Undo技巧

PHPer 要掌握的常用 linux 命令

GitLab 安装、管理、运维

个人网站生成器工具

切换git分支

Git 实现 Laravel 项目的自动化部署

Linux bash总结

GitHubDaily 分享内容定期整理与分类

数据结构与算法/leetcode/lintcode题解

来自不同开发人员为大学生收集整理的一系列资源

整合了编程竞赛有趣又实用的知识站点

ssh example

《后端架构师技术图谱》

Git 的奇技淫巧

Linux 笔记分享二十(终章):网络命令

搭建Git服务器

入门 Linux 之 从命令行开始

Linux下恢复误删除的文件

Linux 下工作必须会的命令清单

中日合拍的《Git游记》即将正式开机

查看 Git 文件变动历史

Git的奇技淫巧

使用GitBook+Github编写文档书籍

猴子都能懂得git

Git commit emoji

git 学习笔记