update docs

pull/11/head
Zhang Peng 2019-11-22 13:36:55 +08:00
parent 74a1b7fb2f
commit 9c162aa61b
23 changed files with 526 additions and 6617 deletions

107
README.md
View File

@ -1,16 +1,44 @@
# Linux 教程 <div align="center">
<h1>Linux 教程</h1>
</div>
> 🔁 项目同步维护在 [github](https://github.com/dunwu/linux-tutorial) | [gitee](https://gitee.com/turnon/linux-tutorial) > 🔁 项目同步维护在 [github](https://github.com/dunwu/linux-tutorial) | [gitee](https://gitee.com/turnon/linux-tutorial)
> >
> 📖 [电子书](https://dunwu.github.io/linux-tutorial/) | [电子书(国内)](http://turnon.gitee.io/linux-tutorial/) > 📖 [电子书](https://dunwu.github.io/linux-tutorial/) | [电子书(国内)](http://turnon.gitee.io/linux-tutorial/)
| 🛠 | 🐚 | 📝 | 📚 | | 📖 | 🐚 | 📚 |
| :-------------------: | :-----------------------: | :-----------: | :-------------------: | | :-----------: | :-----------: | :-----------: |
| [软件运维](#软件运维) | [Shell 脚本](#Shell-脚本) | [教程](#教程) | [学习资源](#学习资源) | | [文章](#文章) | [脚本](#脚本) | [资源](#资源) |
## 软件运维 ## 文章
> 本章节内容介绍日常开发中常见的一些软件、工具的安装、配置。 ### Linux 命令
> 学习 Linux 的第一步:当然是从 [Linux 命令](docs/linux/cli/README.md) 入手了。
- [查看 Linux 命令帮助信息](docs/linux/cli/查看Linux命令帮助信息.md)
- [Linux 文件目录管理](docs/linux/cli/Linux文件目录管理.md)
- [Linux 文件内容查看命令](docs/linux/cli/Linux文件内容查看编辑.md)
- [Linux 文件压缩和解压](docs/linux/cli/Linux文件压缩和解压.md)
- [Linux 用户管理](docs/linux/cli/Linux用户管理.md)
- [Linux 系统管理](docs/linux/cli/Linux系统管理.md)
- [Linux 网络管理](docs/linux/cli/Linux网络管理.md)
- [Linux 硬件管理](docs/linux/cli/Linux硬件管理.md)
- [Linux 软件管理](docs/linux/cli/Linux硬件管理.md)
### Linux 系统运维
> Linux 系统的常见运维工作。
- [linux 典型运维应用](linux/ops/linux典型运维应用.md)
- [samba 使用详解](linux/ops/samba使用详解.md)
- [Systemd 教程](linux/ops/systemd.md)
- [Vim 应用指南](linux/ops/vim.md)
- [Zsh 应用指南](linux/ops/zsh.md)
### 软件运维
> 部署在 Linux 系统上的软件运维。
> >
> 配套安装脚本:🐚 [软件运维配置脚本集合](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/soft) > 配套安装脚本:🐚 [软件运维配置脚本集合](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/soft)
@ -28,16 +56,25 @@
- [Elastic 运维](docs/linux/soft/elastic) - [Elastic 运维](docs/linux/soft/elastic)
- [Kafka 运维](docs/linux/soft/kafka-install.md) - [Kafka 运维](docs/linux/soft/kafka-install.md)
- [RocketMQ 运维](docs/linux/soft/rocketmq-install.md) - [RocketMQ 运维](docs/linux/soft/rocketmq-install.md)
- [Zookeeper 运维](docs/linux/soft/zookeeper-install.md) - [Zookeeper 运维](https://github.com/dunwu/javaweb/blob/master/docs/technology/monitor/zookeeper-ops.md)
- [Nacos 运维](docs/linux/soft/nacos-install.md) - [Nacos 运维](docs/linux/soft/nacos-install.md)
- 服务器 - 服务器
- [Nginx 教程](https://github.com/dunwu/nginx-tutorial) - [Nginx 教程 📚](https://github.com/dunwu/nginx-tutorial)
- [Tomcat 运维](docs/linux/soft/tomcat-install.md) - [Tomcat 运维](linux/soft/tomcat-install.md)
- 数据库 - [数据库 📚](https://github.com/dunwu/db-tutorial)
- [Mongodb 运维](docs/linux/soft/mongodb-ops.md) - [Mysql 运维](https://github.com/dunwu/db-tutorial/blob/master/docs/sql/mysql/mysql-ops.md)
- [Redis 运维](docs/linux/soft/redis-ops.md) - [Redis 运维](https://github.com/dunwu/db-tutorial/blob/master/docs/nosql/redis/redis-ops.md)
## Shell 脚本 ### 扩展
- [Docker 教程](docs/docker)
- [Docker 应用指南](docs/docker/docker.md)
- [Docker Cheat Sheet](docs/docker/docker-cheat-sheet.md)
- [一篇文章让你彻底掌握 Python](https://github.com/dunwu/blog/blob/master/source/_posts/coding/python.md)
- [一篇文章让你彻底掌握 Shell](https://github.com/dunwu/blog/blob/master/source/_posts/coding/shell.md)
- [Git 从入门到精通](https://github.com/dunwu/blog/blob/master/source/_posts/tools/git.md)
## 脚本
### Shell 脚本大全 ### Shell 脚本大全
@ -45,54 +82,24 @@
源码:[**Shell 脚本大全**](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/sys) 源码:[**Shell 脚本大全**](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/sys)
### CentOS 常规操作运维脚本集合 ### CentOS 运维脚本集合
本人作为一名 Java 后端,苦于经常在 CentOS 环境上开荒虚拟机。为提高效率,写了一套 Shell 脚本,提供如下功能:安装常用 lib 库、命令工具、设置 DNS、NTP、配置国内 yum 源、一键安装常用软件等。 本人作为一名 Java 后端,苦于经常在 CentOS 环境上开荒虚拟机。为提高效率,写了一套 Shell 脚本,提供如下功能:安装常用 lib 库、命令工具、设置 DNS、NTP、配置国内 yum 源、一键安装常用软件等。
源码:[**CentOS 常规操作运维脚本集合**](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/sys) 源码:[**CentOS 常规操作运维脚本集合**](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/sys)
## 教程 ## 资源
- [Linux 命令教程](docs/linux/cli/README.md) - **Linux 命令**
- [查看 Linux 命令帮助信息](docs/linux/cli/查看Linux命令帮助信息.md)
- [Linux 文件目录管理](docs/linux/cli/Linux文件目录管理.md)
- [Linux 文件内容查看命令](docs/linux/cli/Linux文件内容查看编辑.md)
- [Linux 文件压缩和解压](docs/linux/cli/Linux文件压缩和解压.md)
- [Linux 用户管理](docs/linux/cli/Linux用户管理.md)
- [Linux 系统管理](docs/linux/cli/Linux系统管理.md)
- [Linux 网络管理](docs/linux/cli/Linux网络管理.md)
- [Linux 硬件管理](docs/linux/cli/Linux硬件管理.md)
- [Linux 软件管理](docs/linux/cli/Linux硬件管理.md)
- [Docker 教程](docs/docker)
- [Docker 应用指南](docs/docker/docker.md)
- [Docker Cheat Sheet](docs/docker/docker-cheat-sheet.md)
- [Git 教程](docs/git/README.md)
- [Git 快速指南](docs/git/git-quickstart.md)
- [Git 配置](docs/git/git-configuration.md)
- [git-flow 工作流](docs/git/git-flow.md)
- [Git 常见问题](docs/git/git-faq.md)
- 运维
- [linux 典型运维应用](docs/linux/ops/linux典型运维应用.md)
- [samba 使用详解](docs/linux/ops/samba使用详解.md)
- [Systemd 教程](docs/linux/ops/systemd.md)
- 脚本
- [Vim 应用指南](docs/linux/ops/vim.md)
- [Zsh 应用指南](docs/linux/ops/zsh.md)
- [Shell 教程](docs/linux/ops/shell.md)
- [Python 教程](docs/linux/ops/python.md)
## 学习资源
- 命令行检索
- [Linux 命令大全](http://man.linuxde.net/) - [Linux 命令大全](http://man.linuxde.net/)
- [linux-command](https://jaywcjlove.gitee.io/linux-command/) - [linux-command](https://jaywcjlove.gitee.io/linux-command/)
- 社区网站 - **社区网站**
- [Linux 中国](https://linux.cn/) - 各种资讯、文章、技术 - [Linux 中国](https://linux.cn/) - 各种资讯、文章、技术
- [实验楼](https://www.shiyanlou.com/) - 免费提供了 Linux 在线环境,不用在自己机子上装系统也可以学习 Linux超方便实用。 - [实验楼](https://www.shiyanlou.com/) - 免费提供了 Linux 在线环境,不用在自己机子上装系统也可以学习 Linux超方便实用。
- [鸟哥的 linux 私房菜](http://linux.vbird.org/) - 非常适合 Linux 入门初学者看的教程。 - [鸟哥的 linux 私房菜](http://linux.vbird.org/) - 非常适合 Linux 入门初学者看的教程。
- [Linux 公社](http://www.linuxidc.com/) - Linux 相关的新闻、教程、主题、壁纸都有。 - [Linux 公社](http://www.linuxidc.com/) - Linux 相关的新闻、教程、主题、壁纸都有。
- [Linux Today](http://www.linuxde.net) - Linux 新闻资讯发布Linux 职业技术学习!。 - [Linux Today](http://www.linuxde.net) - Linux 新闻资讯发布Linux 职业技术学习!。
- 知识相关 - **知识相关**
- [Linux 思维导图整理](http://www.jianshu.com/p/59f759207862) - [Linux 思维导图整理](http://www.jianshu.com/p/59f759207862)
- [Linux 初学者进阶学习资源整理](http://www.jianshu.com/p/fe2a790b41eb) - [Linux 初学者进阶学习资源整理](http://www.jianshu.com/p/fe2a790b41eb)
- [Linux 基础入门(新版)](https://www.shiyanlou.com/courses/1) - [Linux 基础入门(新版)](https://www.shiyanlou.com/courses/1)
@ -101,7 +108,7 @@
- [Linux 编程之内存映射](https://www.shiyanlou.com/questions/2992) - [Linux 编程之内存映射](https://www.shiyanlou.com/questions/2992)
- [Linux 知识点小结](https://blog.huachao.me/2016/1/Linux%E7%9F%A5%E8%AF%86%E7%82%B9%E5%B0%8F%E7%BB%93/) - [Linux 知识点小结](https://blog.huachao.me/2016/1/Linux%E7%9F%A5%E8%AF%86%E7%82%B9%E5%B0%8F%E7%BB%93/)
- [10 大白帽黑客专用的 Linux 操作系统](https://linux.cn/article-6971-1.html) - [10 大白帽黑客专用的 Linux 操作系统](https://linux.cn/article-6971-1.html)
- 软件工具 - **软件工具**
- [超赞的 Linux 软件](https://www.gitbook.com/book/alim0x/awesome-linux-software-zh_cn/details) Github 仓库[Zh](https://github.com/alim0x/Awesome-Linux-Software-zh_CN) [En](https://github.com/VoLuong/Awesome-Linux-Software) - [超赞的 Linux 软件](https://www.gitbook.com/book/alim0x/awesome-linux-software-zh_cn/details) Github 仓库[Zh](https://github.com/alim0x/Awesome-Linux-Software-zh_CN) [En](https://github.com/VoLuong/Awesome-Linux-Software)
- [程序员喜欢的 9 款最佳的 Linux 文件比较工具](http://os.51cto.com/art/201607/513796.htm) - [程序员喜欢的 9 款最佳的 Linux 文件比较工具](http://os.51cto.com/art/201607/513796.htm)
- [提高 Linux 开发效率的 5 个工具](http://www.codeceo.com/article/5-linux-productivity-tools.html) - [提高 Linux 开发效率的 5 个工具](http://www.codeceo.com/article/5-linux-productivity-tools.html)
@ -116,7 +123,7 @@
- [Webflow (Adobe Muse)](https://webflow.com/) 一款可以帮助用户不用编码就可以快速创建网站的谷歌浏览器插件。 - [Webflow (Adobe Muse)](https://webflow.com/) 一款可以帮助用户不用编码就可以快速创建网站的谷歌浏览器插件。
- [Tupi (Adobe Animate)](http://www.maefloresta.com/portal/) 一款可以创建 HTML5 动画的工具。 - [Tupi (Adobe Animate)](http://www.maefloresta.com/portal/) 一款可以创建 HTML5 动画的工具。
- [Black Magic Fusion (Adobe After Effects)](https://www.blackmagicdesign.com) 一款先进的合成软件,广泛应用于视觉特效、广电影视设计以及 3D 动画设计等领域。 - [Black Magic Fusion (Adobe After Effects)](https://www.blackmagicdesign.com) 一款先进的合成软件,广泛应用于视觉特效、广电影视设计以及 3D 动画设计等领域。
- 中国开源镜像站点 - **中国开源镜像**
- [阿里云开源镜像站](http://mirrors.aliyun.com/) - [阿里云开源镜像站](http://mirrors.aliyun.com/)
- [网易开源镜像站](http://mirrors.163.com/) - [网易开源镜像站](http://mirrors.163.com/)
- [搜狐开源镜像站](http://mirrors.sohu.com/) - [搜狐开源镜像站](http://mirrors.sohu.com/)

View File

@ -0,0 +1,63 @@
###################################################################################
# /etc/sysctl.conf 文件用于配置 Linux 内核及网络
# @author: Zhang Peng
###################################################################################
# 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接默认为0表示关闭
net.ipv4.tcp_tw_reuse = 1
# 表示开启TCP连接中TIME-WAIT sockets的快速回收默认为0表示关闭。
net.ipv4.tcp_tw_recycle = 1
# 如果套接字由本端要求关闭这个参数决定了它保持在FIN-WAIT-2状态的时间。
net.ipv4.tcp_fin_timeout = 2
# 避免放大攻击
net.ipv4.icmp_echo_ignore_broadcasts = 1
# 开启恶意icmp错误消息保护
net.ipv4.icmp_ignore_bogus_error_responses = 1
# 开启SYN洪水攻击保护
net.ipv4.tcp_syncookies = 1
# 开启并记录欺骗,源路由和重定向包
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
# 处理无源路由的包
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# 开启反向路径过滤
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# 确保无人能修改路由表
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
# 不充当路由器
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# 开启execshild
kernel.exec-shield = 1
kernel.randomize_va_space = 1
# IPv6设置
net.ipv6.conf.default.router_solicitations = 0
net.ipv6.conf.default.accept_ra_rtr_pref = 0
net.ipv6.conf.default.accept_ra_pinfo = 0
net.ipv6.conf.default.accept_ra_defrtr = 0
net.ipv6.conf.default.autoconf = 0
net.ipv6.conf.default.dad_transmits = 0
net.ipv6.conf.default.max_addresses = 1
# 优化LB使用的端口
# 增加系统文件描述符限制
fs.file-max = 65535
# 允许更多的PIDs (减少滚动翻转问题); may break some programs 32768
kernel.pid_max = 65536
# 增加系统IP端口限制
net.ipv4.ip_local_port_range = 2000 65535
# 增加TCP最大缓冲区大小
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 87380 8388608
# 增加Linux自动调整TCP缓冲区限制
# 最小,默认和最大可使用的字节数
# 最大值不低于4MB如果你使用非常高的BDP路径可以设置得更高
# Tcp窗口等
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_window_scaling = 1

View File

@ -0,0 +1,8 @@
#!/usr/bin/env bash
# 使用 grep 命令可以用于在文件中查找指定文本
# 在二进制文件中查找字符串
file=$1
keyword=$2
strings ${file} | grep ${keyword}

View File

@ -1,16 +1,44 @@
# Linux 教程 <div align="center">
<h1>Linux 教程</h1>
</div>
> 🔁 项目同步维护在 [github](https://github.com/dunwu/linux-tutorial) | [gitee](https://gitee.com/turnon/linux-tutorial) > 🔁 项目同步维护在 [github](https://github.com/dunwu/linux-tutorial) | [gitee](https://gitee.com/turnon/linux-tutorial)
> >
> 📖 [电子书](https://dunwu.github.io/linux-tutorial/) | [电子书(国内)](http://turnon.gitee.io/linux-tutorial/) > 📖 [电子书](https://dunwu.github.io/linux-tutorial/) | [电子书(国内)](http://turnon.gitee.io/linux-tutorial/)
| 🛠 | 🐚 | 📝 | 📚 | | 📖 | 🐚 | 📚 |
| :-------------------: | :-----------------------: | :-----------: | :-------------------: | | :-----------: | :-----------: | :-----------: |
| [软件运维](#软件运维) | [Shell 脚本](#Shell-脚本) | [教程](#教程) | [学习资源](#学习资源) | | [文章](#文章) | [脚本](#脚本) | [资源](#资源) |
## 软件运维 ## 文章
> 本章节内容介绍日常开发中常见的一些软件、工具的安装、配置。 ### Linux 命令
> 学习 Linux 的第一步:当然是从 [Linux 命令](linux/cli/README.md) 入手了。
- [查看 Linux 命令帮助信息](linux/cli/查看Linux命令帮助信息.md)
- [Linux 文件目录管理](linux/cli/Linux文件目录管理.md)
- [Linux 文件内容查看命令](linux/cli/Linux文件内容查看编辑.md)
- [Linux 文件压缩和解压](linux/cli/Linux文件压缩和解压.md)
- [Linux 用户管理](linux/cli/Linux用户管理.md)
- [Linux 系统管理](linux/cli/Linux系统管理.md)
- [Linux 网络管理](linux/cli/Linux网络管理.md)
- [Linux 硬件管理](linux/cli/Linux硬件管理.md)
- [Linux 软件管理](linux/cli/Linux硬件管理.md)
### Linux 系统运维
> Linux 系统的常见运维工作。
- [linux 典型运维应用](linux/ops/linux典型运维应用.md)
- [samba 使用详解](linux/ops/samba使用详解.md)
- [Systemd 教程](linux/ops/systemd.md)
- [Vim 应用指南](linux/ops/vim.md)
- [Zsh 应用指南](linux/ops/zsh.md)
### 软件运维
> 部署在 Linux 系统上的软件运维。
> >
> 配套安装脚本:🐚 [软件运维配置脚本集合](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/soft) > 配套安装脚本:🐚 [软件运维配置脚本集合](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/soft)
@ -28,16 +56,25 @@
- [Elastic 运维](linux/soft/elastic) - [Elastic 运维](linux/soft/elastic)
- [Kafka 运维](linux/soft/kafka-install.md) - [Kafka 运维](linux/soft/kafka-install.md)
- [RocketMQ 运维](linux/soft/rocketmq-install.md) - [RocketMQ 运维](linux/soft/rocketmq-install.md)
- [Zookeeper 运维](linux/soft/zookeeper-install.md) - [Zookeeper 运维](https://github.com/dunwu/javaweb/blob/master/docs/technology/monitor/zookeeper-ops.md)
- [Nacos 运维](linux/soft/nacos-install.md) - [Nacos 运维](linux/soft/nacos-install.md)
- 服务器 - 服务器
- [Nginx 教程](https://github.com/dunwu/nginx-tutorial) - [Nginx 教程 📚](https://github.com/dunwu/nginx-tutorial)
- [Tomcat 运维](linux/soft/tomcat-install.md) - [Tomcat 运维](linux/soft/tomcat-install.md)
- 数据库 - [数据库 📚](https://github.com/dunwu/db-tutorial)
- [Mongodb 运维](linux/soft/mongodb-ops.md) - [Mysql 运维](https://github.com/dunwu/db-tutorial/blob/master/docs/sql/mysql/mysql-ops.md)
- [Redis 运维](linux/soft/redis-ops.md) - [Redis 运维](https://github.com/dunwu/db-tutorial/blob/master/docs/nosql/redis/redis-ops.md)
## Shell 脚本 ### 扩展
- [Docker 教程](docker)
- [Docker 应用指南](docker/docker.md)
- [Docker Cheat Sheet](docker/docker-cheat-sheet.md)
- [一篇文章让你彻底掌握 Python](https://github.com/dunwu/blog/blob/master/source/_posts/coding/python.md)
- [一篇文章让你彻底掌握 Shell](https://github.com/dunwu/blog/blob/master/source/_posts/coding/shell.md)
- [Git 从入门到精通](https://github.com/dunwu/blog/blob/master/source/_posts/tools/git.md)
## 脚本
### Shell 脚本大全 ### Shell 脚本大全
@ -45,54 +82,24 @@
源码:[**Shell 脚本大全**](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/sys) 源码:[**Shell 脚本大全**](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/sys)
### CentOS 常规操作运维脚本集合 ### CentOS 运维脚本集合
本人作为一名 Java 后端,苦于经常在 CentOS 环境上开荒虚拟机。为提高效率,写了一套 Shell 脚本,提供如下功能:安装常用 lib 库、命令工具、设置 DNS、NTP、配置国内 yum 源、一键安装常用软件等。 本人作为一名 Java 后端,苦于经常在 CentOS 环境上开荒虚拟机。为提高效率,写了一套 Shell 脚本,提供如下功能:安装常用 lib 库、命令工具、设置 DNS、NTP、配置国内 yum 源、一键安装常用软件等。
源码:[**CentOS 常规操作运维脚本集合**](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/sys) 源码:[**CentOS 常规操作运维脚本集合**](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/sys)
## 教程 ## 资源
- [Linux 命令教程](linux/cli/README.md) - **Linux 命令**
- [查看 Linux 命令帮助信息](linux/cli/查看Linux命令帮助信息.md)
- [Linux 文件目录管理](linux/cli/Linux文件目录管理.md)
- [Linux 文件内容查看命令](linux/cli/Linux文件内容查看编辑.md)
- [Linux 文件压缩和解压](linux/cli/Linux文件压缩和解压.md)
- [Linux 用户管理](linux/cli/Linux用户管理.md)
- [Linux 系统管理](linux/cli/Linux系统管理.md)
- [Linux 网络管理](linux/cli/Linux网络管理.md)
- [Linux 硬件管理](linux/cli/Linux硬件管理.md)
- [Linux 软件管理](linux/cli/Linux硬件管理.md)
- [Docker 教程](docker)
- [Docker 应用指南](docker/docker.md)
- [Docker Cheat Sheet](docker/docker-cheat-sheet.md)
- [Git 教程](git/README.md)
- [Git 快速指南](git/git-quickstart.md)
- [Git 配置](git/git-configuration.md)
- [git-flow 工作流](git/git-flow.md)
- [Git 常见问题](git/git-faq.md)
- 运维
- [linux 典型运维应用](linux/ops/linux典型运维应用.md)
- [samba 使用详解](linux/ops/samba使用详解.md)
- [Systemd 教程](linux/ops/systemd.md)
- 脚本
- [Vim 应用指南](linux/ops/vim.md)
- [Zsh 应用指南](linux/ops/zsh.md)
- [Shell 教程](linux/ops/shell.md)
- [Python 教程](linux/ops/python.md)
## 学习资源
- 命令行检索
- [Linux 命令大全](http://man.linuxde.net/) - [Linux 命令大全](http://man.linuxde.net/)
- [linux-command](https://jaywcjlove.gitee.io/linux-command/) - [linux-command](https://jaywcjlove.gitee.io/linux-command/)
- 社区网站 - **社区网站**
- [Linux 中国](https://linux.cn/) - 各种资讯、文章、技术 - [Linux 中国](https://linux.cn/) - 各种资讯、文章、技术
- [实验楼](https://www.shiyanlou.com/) - 免费提供了 Linux 在线环境,不用在自己机子上装系统也可以学习 Linux超方便实用。 - [实验楼](https://www.shiyanlou.com/) - 免费提供了 Linux 在线环境,不用在自己机子上装系统也可以学习 Linux超方便实用。
- [鸟哥的 linux 私房菜](http://linux.vbird.org/) - 非常适合 Linux 入门初学者看的教程。 - [鸟哥的 linux 私房菜](http://linux.vbird.org/) - 非常适合 Linux 入门初学者看的教程。
- [Linux 公社](http://www.linuxidc.com/) - Linux 相关的新闻、教程、主题、壁纸都有。 - [Linux 公社](http://www.linuxidc.com/) - Linux 相关的新闻、教程、主题、壁纸都有。
- [Linux Today](http://www.linuxde.net) - Linux 新闻资讯发布Linux 职业技术学习!。 - [Linux Today](http://www.linuxde.net) - Linux 新闻资讯发布Linux 职业技术学习!。
- 知识相关 - **知识相关**
- [Linux 思维导图整理](http://www.jianshu.com/p/59f759207862) - [Linux 思维导图整理](http://www.jianshu.com/p/59f759207862)
- [Linux 初学者进阶学习资源整理](http://www.jianshu.com/p/fe2a790b41eb) - [Linux 初学者进阶学习资源整理](http://www.jianshu.com/p/fe2a790b41eb)
- [Linux 基础入门(新版)](https://www.shiyanlou.com/courses/1) - [Linux 基础入门(新版)](https://www.shiyanlou.com/courses/1)
@ -101,7 +108,7 @@
- [Linux 编程之内存映射](https://www.shiyanlou.com/questions/2992) - [Linux 编程之内存映射](https://www.shiyanlou.com/questions/2992)
- [Linux 知识点小结](https://blog.huachao.me/2016/1/Linux%E7%9F%A5%E8%AF%86%E7%82%B9%E5%B0%8F%E7%BB%93/) - [Linux 知识点小结](https://blog.huachao.me/2016/1/Linux%E7%9F%A5%E8%AF%86%E7%82%B9%E5%B0%8F%E7%BB%93/)
- [10 大白帽黑客专用的 Linux 操作系统](https://linux.cn/article-6971-1.html) - [10 大白帽黑客专用的 Linux 操作系统](https://linux.cn/article-6971-1.html)
- 软件工具 - **软件工具**
- [超赞的 Linux 软件](https://www.gitbook.com/book/alim0x/awesome-linux-software-zh_cn/details) Github 仓库[Zh](https://github.com/alim0x/Awesome-Linux-Software-zh_CN) [En](https://github.com/VoLuong/Awesome-Linux-Software) - [超赞的 Linux 软件](https://www.gitbook.com/book/alim0x/awesome-linux-software-zh_cn/details) Github 仓库[Zh](https://github.com/alim0x/Awesome-Linux-Software-zh_CN) [En](https://github.com/VoLuong/Awesome-Linux-Software)
- [程序员喜欢的 9 款最佳的 Linux 文件比较工具](http://os.51cto.com/art/201607/513796.htm) - [程序员喜欢的 9 款最佳的 Linux 文件比较工具](http://os.51cto.com/art/201607/513796.htm)
- [提高 Linux 开发效率的 5 个工具](http://www.codeceo.com/article/5-linux-productivity-tools.html) - [提高 Linux 开发效率的 5 个工具](http://www.codeceo.com/article/5-linux-productivity-tools.html)
@ -116,7 +123,7 @@
- [Webflow (Adobe Muse)](https://webflow.com/) 一款可以帮助用户不用编码就可以快速创建网站的谷歌浏览器插件。 - [Webflow (Adobe Muse)](https://webflow.com/) 一款可以帮助用户不用编码就可以快速创建网站的谷歌浏览器插件。
- [Tupi (Adobe Animate)](http://www.maefloresta.com/portal/) 一款可以创建 HTML5 动画的工具。 - [Tupi (Adobe Animate)](http://www.maefloresta.com/portal/) 一款可以创建 HTML5 动画的工具。
- [Black Magic Fusion (Adobe After Effects)](https://www.blackmagicdesign.com) 一款先进的合成软件,广泛应用于视觉特效、广电影视设计以及 3D 动画设计等领域。 - [Black Magic Fusion (Adobe After Effects)](https://www.blackmagicdesign.com) 一款先进的合成软件,广泛应用于视觉特效、广电影视设计以及 3D 动画设计等领域。
- 中国开源镜像站点 - **中国开源镜像**
- [阿里云开源镜像站](http://mirrors.aliyun.com/) - [阿里云开源镜像站](http://mirrors.aliyun.com/)
- [网易开源镜像站](http://mirrors.163.com/) - [网易开源镜像站](http://mirrors.163.com/)
- [搜狐开源镜像站](http://mirrors.sohu.com/) - [搜狐开源镜像站](http://mirrors.sohu.com/)

View File

@ -1,7 +1,7 @@
<div align="center"><img width="100px" src="http://dunwu.test.upcdn.net/common/logo/zp.png"/></div> ![logo](http://dunwu.test.upcdn.net/common/logo/zp.png)
# linux-tutorial # linux-tutorial
> Linux 教程 > linux-tutorial 是一个 Linux 教程
[开始阅读](README.md) [开始阅读](README.md)

View File

@ -1,58 +0,0 @@
# Git 教程
## :memos: 知识点
- [Git 快速指南](git-quickstart.md)
- [Git 配置](git-configuration.md)
- [git-flow 工作流](git-flow.md)
- [Git 常见问题](git-faq.md)
## 📚 学习资源
### 官方资源
- [Git 官网](https://git-scm.com/)
- [Git Github](https://github.com/git/git)
### 模板
- [gitignore 模板](https://github.com/github/gitignore) - .gitignore 文件模板
- [gitattributes 模板](https://github.com/alexkaratarakis/gitattributes) - .gitattributes 文件模板
- [github-cheat-sheet](https://github.com/tiimgreen/github-cheat-sheet) - git 命令简略图表
### Git 书
- [Git 官方推荐教程](https://git-scm.com/book/zh/v2) - Scott Chacon 的 Git 书。
### Git 教程
- [Git 中文教程](https://github.com/geeeeeeeeek/git-recipes)
- [廖雪峰的 Git 教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000)
- [有关 git 的学习资源](https://github.com/xirong/my-git)
### 文章
- [Git Cookbook](https://github.com/k88hudson/git-flight-rules/blob/master/README_zh-CN.md)
- [Git 奇技淫巧](https://github.com/521xueweihan/git-tips)
- [Git 风格指南](https://github.com/aseaday/git-style-guide)
### Git 工具
- [guis](https://git-scm.com/downloads/guis) - Git 官网展示的客户端工具列表。
- [gogs](https://github.com/gogits/gogs) - 极易搭建的自助 Git 服务。
- [gitflow](https://github.com/nvie/gitflow) - 应用 [fit-flow](http://nvie.com/posts/a-successful-git-branching-model/) 模型的工具。
- [firstaidgit.io](http://firstaidgit.io/) 一个可搜索的最常被问到的 Git 的问题
- [git-extra-commands](https://github.com/unixorn/git-extra-commands) - 一堆有用的额外的 Git 脚本
- [git-extras](https://github.com/tj/git-extras) - GIT 工具集 -- repo summary, repl, changelog population, author commit percentages and more
- [git-fire](https://github.com/qw3rtman/git-fire) - git-fire 是一个 Git 插件,用于帮助在紧急情况下添加所有当前文件, 做提交(committing), 和推(push)到一个新分支(阻止合并冲突)。
- [git-tips](https://github.com/git-tips/tips) - Git 小提示
- [git-town](https://github.com/Originate/git-town) - 通用,高级 Git 工作流支持! http://www.git-town.com
### GUI 客户端(GUI Clients)
- [GitKraken](https://www.gitkraken.com/) - 豪华的 Git 客户端 Windows, Mac & Linux
- [git-cola](https://git-cola.github.io/) - 另外一个 Git 客户端 Windows & OS X
- [GitUp](https://github.com/git-up/GitUp) - 一个新的 Git 客户端,在处理 Git 的复杂性上有自己的特点
- [gitx-dev](https://rowanj.github.io/gitx/) - 图形化的 Git 客户端 OS X
- [Source Tree](https://www.sourcetreeapp.com/) - 免费的图形化 Git 客户端 Windows & OS X
- [Tower](http://www.git-tower.com/) - 图形化 Git 客户端 OS X(付费)

View File

@ -1,220 +0,0 @@
# Git 配置
## 配置 Git
Git 使用一系列配置文件来保存你自定义的行为。 它首先会查找 `/etc/gitconfig` 文件,该文件含有系统里每位用户及他们所拥有的仓库的配置值。 如果你传递 `--system` 选项给 `git config`,它就会读写该文件。
接下来 Git 会查找每个用户的 `\~/.gitconfig` 文件(或者 `\~/.config/git/config` 文件)。 你可以传递 `--global` 选项让 Git 读写该文件。
最后 Git 会查找你正在操作的版本库所对应的 Git 目录下的配置文件(`.git/config`)。 这个文件中的值只对该版本库有效。
以上三个层次中每层的配置(系统、全局、本地)都会覆盖掉上一层次的配置,所以 `.git/config` 中的值会覆盖掉 `/etc/gitconfig` 中所对应的值。
## 客户端基本配置
### `core.editor`
默认情况下Git 会调用环境变量(`$VISUAL` 或 `$EDITOR`)设置的任意文本编辑器,如果没有设置,会调用 `vi` 来创建和编辑你的提交以及标签信息。 你可以使用 `core.editor` 选项来修改默认的编辑器:
```
$ git config --global core.editor emacs
```
现在无论你定义了什么终端编辑器Git 都会调用 Emacs 编辑信息。
### `commit.template`
如果把此项指定为你的系统上某个文件的路径,当你提交的时候, Git 会使用该文件的内容作为提交的默认信息。 例如:假设你创建了一个叫 `\~/.gitmessage.txt` 的模板文件,类似这样:
```
subject line
what happened
[ticket: X]
```
要想让 Git 把它作为运行 `git commit` 时显示在你的编辑器中的默认信息, 如下设置 `commit.template`
```
$ git config --global commit.template ~/.gitmessage.txt
$ git commit
```
然后当你提交时,编辑器中就会显示如下的提交信息占位符:
```
subject line
what happened
[ticket: X]
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: lib/test.rb
#
~
~
".git/COMMIT_EDITMSG" 14L, 297C
```
如果你的团队对提交信息有格式要求,可以在系统上创建一个文件,并配置 Git 把它作为默认的模板,这样可以更加容易地使提交信息遵循格式。
### `core.pager`
该配置项指定 Git 运行诸如 `log``diff` 等命令所使用的分页器。 你可以把它设置成用 `more` 或者任何你喜欢的分页器(默认用的是 `less`),当然也可以设置成空字符串,关闭该选项:
```
$ git config --global core.pager ''
```
这样不管命令的输出量多少Git 都会在一页显示所有内容。
### `user.signingkey`
如果你要创建经签署的含附注的标签(正如 [签署工作](https://git-scm.com/book/zh/v2/ch00/r_signing) 所述),那么把你的 GPG 签署密钥设置为配置项会更好。 如下设置你的密钥 ID
```
$ git config --global user.signingkey <gpg-key-id>
```
现在,你每次运行 `git tag` 命令时,即可直接签署标签,而无需定义密钥:
```
$ git tag -s <tag-name>
```
### `core.excludesfile`
正如 [忽略文件](https://git-scm.com/book/zh/v2/ch00/r_ignoring) 所述,你可以在你的项目的 `.gitignore` 文件里面规定无需纳入 Git 管理的文件的模板,这样它们既不会出现在未跟踪列表,也不会在你运行 `git add` 后被暂存。
不过有些时候,你想要在你所有的版本库中忽略掉某一类文件。 如果你的操作系统是 OS X很可能就是指`.DS_Store`。 如果你把 Emacs 或 Vim 作为首选的编辑器,你肯定知道以 `\~` 结尾的临时文件。
这个配置允许你设置类似于全局生效的 `.gitignore` 文件。 如果你按照下面的内容创建一个`\~/.gitignore_global` 文件:
```
*~
.DS_Store
```
……然后运行 `git config --global core.excludesfile \~/.gitignore_global`Git 将把那些文件永远地拒之门外。
### `help.autocorrect`
假如你打错了一条命令,会显示:
```
$ git chekcout master
git'chekcout' 不是一个 git 命令。参见 'git --help'。
您指的是这个么?
checkout
```
Git 会尝试猜测你的意图,但是它不会越俎代庖。 如果你把 `help.autocorrect` 设置成 1那么只要有一个命令被模糊匹配到了Git 会自动运行该命令。
```
$ git chekcout master
警告:您运行一个不存在的 Git 命令 'chekcout'。继续执行假定您要要运行的
是 'checkout'
在 0.1 秒钟后自动运行...
```
注意提示信息中的“0.1 秒”。`help.autocorrect` 接受一个代表十分之一秒的整数。 所以如果你把它设置为 50, Git 将在自动执行命令前给你 5 秒的时间改变主意。
## 格式化与多余的空白字符
格式化与多余的空白字符是许多开发人员在协作时,特别是在跨平台情况下,不时会遇到的令人头疼的琐碎的问题。 由于编辑器的不同或者文件行尾的换行符在 Windows 下被替换了,一些细微的空格变化会不经意地混入提交的补丁或其它协作成果中。 不用怕Git 提供了一些配置项来帮助你解决这些问题。
### `core.autocrlf`
假如你正在 Windows 上写程序,而你的同伴用的是其他系统(或相反),你可能会遇到 CRLF 问题。 这是因为 Windows 使用回车CR和换行LF两个字符来结束一行而 Mac 和 Linux 只使用换行LF一个字符。 虽然这是小问题,但它会极大地扰乱跨平台协作。许多 Windows 上的编辑器会悄悄把行尾的换行字符转换成回车和换行,或在用户按下 Enter 键时,插入回车和换行两个字符。
Git 可以在你提交时自动地把回车和换行转换成换行,而在检出代码时把换行转换成回车和换行。 你可以用 `core.autocrlf` 来打开此项功能。 如果是在 Windows 系统上,把它设置成 `true`,这样在检出代码时,换行会被转换成回车和换行:
```
$ git config --global core.autocrlf true
```
如果使用以换行作为行结束符的 Linux 或 Mac你不需要 Git 在检出文件时进行自动的转换;然而当一个以回车加换行作为行结束符的文件不小心被引入时,你肯定想让 Git 修正。 你可以把 `core.autocrlf` 设置成 input 来告诉 Git 在提交时把回车和换行转换成换行,检出时不转换:
```
$ git config --global core.autocrlf input
```
这样在 Windows 上的检出文件中会保留回车和换行,而在 Mac 和 Linux 上,以及版本库中会保留换行。
如果你是 Windows 程序员,且正在开发仅运行在 Windows 上的项目,可以设置 `false` 取消此功能,把回车保留在版本库中:
```
$ git config --global core.autocrlf false
```
### `core.whitespace`
Git 预先设置了一些选项来探测和修正多余空白字符问题。 它提供了六种处理多余空白字符的主要选项 —— 其中三个默认开启,另外三个默认关闭,不过你可以自由地设置它们。
默认被打开的三个选项是:`blank-at-eol`,查找行尾的空格;`blank-at-eof`,盯住文件底部的空行;`space-before-tab`,警惕行头 tab 前面的空格。
默认被关闭的三个选项是:`indent-with-non-tab`,揪出以空格而非 tab 开头的行(你可以用 `tabwidth`选项控制它);`tab-in-indent`,监视在行头表示缩进的 tab`cr-at-eol`,告诉 Git 忽略行尾的回车。
通过设置 `core.whitespace`,你可以让 Git 按照你的意图来打开或关闭以逗号分割的选项。 要想关闭某个选项,你可以在输入设置选项时不指定它或在它前面加个 `-`。 例如,如果你想要打开除 `cr-at-eol` 之外的所有选项:
```
$ git config --global core.whitespace \
trailing-space,space-before-tab,indent-with-non-tab
```
当你运行 `git diff` 命令并尝试给输出着色时Git 将探测到这些问题,因此你在提交前就能修复它们。 用`git apply` 打补丁时你也会从中受益。 如果正准备应用的补丁存有特定的空白问题,你可以让 Git 在应用补丁时发出警告:
```
$ git apply --whitespace=warn <patch>
```
或者让 Git 在打上补丁前自动修正此问题:
```
$ git apply --whitespace=fix <patch>
```
这些选项也能运用于 `git rebase`。 如果提交了有空白问题的文件,但还没推送到上游,你可以运行 `git rebase --whitespace=fix` 来让 Git 在重写补丁时自动修正它们。
## 服务器端配置
Git 服务器端的配置项相对来说并不多,但仍有一些饶有生趣的选项值得你一看。
### `receive.fsckObjects`
Git 能够确认每个对象的有效性以及 SHA-1 检验和是否保持一致。 但 Git 不会在每次推送时都这么做。这个操作很耗时间,很有可能会拖慢提交的过程,特别是当库或推送的文件很大的情况下。 如果想在每次推送时都要求 Git 检查一致性,设置 `receive.fsckObjects` 为 true 来强迫它这么做:
```
$ git config --system receive.fsckObjects true
```
现在 Git 会在每次推送生效前检查库的完整性,确保没有被有问题的客户端引入破坏性数据。
### `receive.denyNonFastForwards`
如果你变基已经被推送的提交,继而再推送,又或者推送一个提交到远程分支,而这个远程分支当前指向的提交不在该提交的历史中,这样的推送会被拒绝。 这通常是个很好的策略,但有时在变基的过程中,你确信自己需要更新远程分支,可以在 push 命令后加 `-f` 标志来强制更新force-update
要禁用这样的强制更新推送force-pushes可以设置 `receive.denyNonFastForwards`
```
$ git config --system receive.denyNonFastForwards true
```
稍后我们会提到,用服务器端的接收钩子也能达到同样的目的。 那种方法可以做到更细致的控制例如禁止某一类用户做非快进non-fast-forwards推送。
### `receive.denyDeletes`
有一些方法可以绕过 `denyNonFastForwards` 策略。其中一种是先删除某个分支,再连同新的引用一起推送回该分支。 把 `receive.denyDeletes` 设置为 true 可以把这个漏洞补上:
```
$ git config --system receive.denyDeletes true
```
这样会禁止通过推送删除分支和标签 — 没有用户可以这么做。 要删除远程分支,必须从服务器手动删除引用文件。 通过用户访问控制列表ACL也能够在用户级的粒度上实现同样的功能你将在 [使用强制策略的一个例子](https://git-scm.com/book/zh/v2/ch00/r_an_example_git_enforced_policy) 一节学到具体的做法。

View File

@ -1,858 +0,0 @@
# Git 常见问题
## 编辑提交(editting commits)
### 我刚才提交了什么
如果你用 `git commit -a` 提交了一次变化(changes),而你又不确定到底这次提交了哪些内容。 你就可以用下面的命令显示当前`HEAD`上的最近一次的提交(commit):
```bash
(master)$ git show
```
或者
```bash
$ git log -n1 -p
```
### 我的提交信息(commit message)写错了
如果你的提交信息(commit message)写错了且这次提交(commit)还没有推(push), 你可以通过下面的方法来修改提交信息(commit message):
```bash
$ git commit --amend
```
这会打开你的默认编辑器, 在这里你可以编辑信息. 另一方面, 你也可以用一条命令一次完成:
```bash
$ git commit --amend -m 'xxxxxxx'
```
如果你已经推(push)了这次提交(commit), 你可以修改这次提交(commit)然后强推(force push), 但是不推荐这么做。
### 我提交(commit)里的用户名和邮箱不对
如果这只是单个提交(commit),修改它:
```bash
$ git commit --amend --author "New Authorname <authoremail@mydomain.com>"
```
如果你需要修改所有历史, 参考 'git filter-branch'的指南页.
### 我想从一个提交(commit)里移除一个文件
通过下面的方法,从一个提交(commit)里移除一个文件:
```bash
$ git checkout HEAD^ myfile
$ git add -A
$ git commit --amend
```
这将非常有用,当你有一个开放的补丁(open patch),你往上面提交了一个不必要的文件,你需要强推(force push)去更新这个远程补丁。
### 我想删除我的的最后一次提交(commit)
如果你需要删除推了的提交(pushed commits),你可以使用下面的方法。可是,这会不可逆的改变你的历史,也会搞乱那些已经从该仓库拉取(pulled)了的人的历史。简而言之,如果你不是很确定,千万不要这么做。
```bash
$ git reset HEAD^ --hard
$ git push -f [remote] [branch]
```
如果你还没有推到远程, 把 Git 重置(reset)到你最后一次提交前的状态就可以了(同时保存暂存的变化):
```
(my-branch*)$ git reset --soft HEAD@{1}
```
这只能在没有推送之前有用. 如果你已经推了, 唯一安全能做的是 `git revert SHAofBadCommit` 那会创建一个新的提交(commit)用于撤消前一个提交的所有变化(changes) 或者, 如果你推的这个分支是 rebase-safe 的 (例如: 其它开发者不会从这个分支拉), 只需要使用 `git push -f` 更多, 请参考 [the above section](#deleteremove-last-pushed-commit)。
### 删除任意提交(commit)
同样的警告:不到万不得已的时候不要这么做.
```bash
$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT
$ git push -f [remote] [branch]
```
或者做一个 [交互式 rebase](#interactive-rebase) 删除那些你想要删除的提交(commit)里所对应的行。
### 我尝试推一个修正后的提交(amended commit)到远程,但是报错:
```bash
To https://github.com/yourusername/repo.git
! [rejected] mybranch -> mybranch (non-fast-forward)
error: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
```
注意, rebasing(见下面)和修正(amending)会用一个**新的提交(commit)代替旧的**, 所以如果之前你已经往远程仓库上推过一次修正前的提交(commit),那你现在就必须强推(force push) (`-f`)。 注意 &ndash; _总是_ 确保你指明一个分支!
```bash
(my-branch)$ git push origin mybranch -f
```
一般来说, **要避免强推**. 最好是创建和推(push)一个新的提交(commit),而不是强推一个修正后的提交。后者会使那些与该分支或该分支的子分支工作的开发者,在源历史中产生冲突。
### 我意外的做了一次硬重置(hard reset),我想找回我的内容
如果你意外的做了 `git reset --hard`, 你通常能找回你的提交(commit), 因为 Git 对每件事都会有日志,且都会保存几天。
```bash
(master)$ git reflog
```
你将会看到一个你过去提交(commit)的列表, 和一个重置的提交。 选择你想要回到的提交(commit)的 SHA再重置一次:
```bash
(master)$ git reset --hard SHA1234
```
这样就完成了。
## 暂存(Staging)
### 我需要把暂存的内容添加到上一次的提交(commit)
```bash
(my-branch*)$ git commit --amend
```
### 我想要暂存一个新文件的一部分,而不是这个文件的全部
一般来说, 如果你想暂存一个文件的一部分, 你可这样做:
```bash
$ git add --patch filename.x
```
`-p` 简写。这会打开交互模式, 你将能够用 `s` 选项来分隔提交(commit) 然而, 如果这个文件是新的, 会没有这个选择, 添加一个新文件时, 这样做:
```bash
$ git add -N filename.x
```
然后, 你需要用 `e` 选项来手动选择需要添加的行,执行 `git diff --cached` 将会显示哪些行暂存了哪些行只是保存在本地了。
### 我想把在一个文件里的变化(changes)加到两个提交(commit)里
`git add` 会把整个文件加入到一个提交. `git add -p` 允许交互式的选择你想要提交的部分.
### 我想把暂存的内容变成未暂存,把未暂存的内容暂存起来
这个有点困难, 我能想到的最好的方法是先 stash 未暂存的内容, 然后重置(reset),再 pop 第一步 stashed 的内容, 最后再 add 它们。
```bash
$ git stash -k
$ git reset --hard
$ git stash pop
$ git add -A
```
## 未暂存(Unstaged)的内容
### 我想把未暂存的内容移动到一个新分支
```bash
$ git checkout -b my-branch
```
### 我想把未暂存的内容移动到另一个已存在的分支
```bash
$ git stash
$ git checkout my-branch
$ git stash pop
```
### 我想丢弃本地未提交的变化(uncommitted changes)
如果你只是想重置源(origin)和你本地(local)之间的一些提交(commit),你可以:
```bash
# one commit
(my-branch)$ git reset --hard HEAD^
# two commits
(my-branch)$ git reset --hard HEAD^^
# four commits
(my-branch)$ git reset --hard HEAD~4
# or
(master)$ git checkout -f
```
重置某个特殊的文件, 你可以用文件名做为参数:
```bash
$ git reset filename
```
### 我想丢弃某些未暂存的内容
如果你想丢弃工作拷贝中的一部分内容,而不是全部。
签出(checkout)不需要的内容,保留需要的。
```bash
$ git checkout -p
# Answer y to all of the snippets you want to drop
```
另外一个方法是使用 `stash` Stash 所有要保留下的内容, 重置工作拷贝, 重新应用保留的部分。
```bash
$ git stash -p
# Select all of the snippets you want to save
$ git reset --hard
$ git stash pop
```
或者, stash 你不需要的部分, 然后 stash drop。
```bash
$ git stash -p
# Select all of the snippets you don't want to save
$ git stash drop
```
## 分支(Branches)
### 我从错误的分支拉取了内容,或把内容拉取到了错误的分支
这是另外一种使用 `git reflog` 情况,找到在这次错误拉(pull) 之前 HEAD 的指向。
```bash
(master)$ git reflog
ab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward
c5bc55a HEAD@{1}: checkout: checkout message goes here
```
重置分支到你所需的提交(desired commit):
```bash
$ git reset --hard c5bc55a
```
完成。
### 我想扔掉本地的提交(commit),以便我的分支与远程的保持一致
先确认你没有推(push)你的内容到远程。
`git status` 会显示你领先(ahead)源(origin)多少个提交:
```bash
(my-branch)$ git status
# On branch my-branch
# Your branch is ahead of 'origin/my-branch' by 2 commits.
# (use "git push" to publish your local commits)
#
```
一种方法是:
```bash
(master)$ git reset --hard origin/my-branch
```
### 我需要提交到一个新分支,但错误的提交到了 master
在 master 下创建一个新分支,不切换到新分支,仍在 master 下:
```bash
(master)$ git branch my-branch
```
把 master 分支重置到前一个提交:
```bash
(master)$ git reset --hard HEAD^
```
`HEAD^``HEAD^1` 的简写,你可以通过指定要设置的`HEAD`来进一步重置。
或者, 如果你不想使用 `HEAD^`, 找到你想重置到的提交(commit)的 hash(`git log` 能够完成) 然后重置到这个 hash。 使用`git push` 同步内容到远程。
例如, master 分支想重置到的提交的 hash 为`a13b85e`:
```bash
(master)$ git reset --hard a13b85e
HEAD is now at a13b85e
```
签出(checkout)刚才新建的分支继续工作:
```bash
(master)$ git checkout my-branch
```
### 我想保留来自另外一个 ref-ish 的整个文件
假设你正在做一个原型方案(原文为 working spike (see note)), 有成百的内容,每个都工作得很好。现在, 你提交到了一个分支,保存工作内容:
```bash
(solution)$ git add -A && git commit -m "Adding all changes from this spike into one big commit."
```
当你想要把它放到一个分支里 (可能是`feature`, 或者 `develop`), 你关心是保持整个文件的完整,你想要一个大的提交分隔成比较小。
假设你有:
- 分支 `solution`, 拥有原型方案, 领先 `develop` 分支。
- 分支 `develop`, 在这里你应用原型方案的一些内容。
我去可以通过把内容拿到你的分支里,来解决这个问题:
```bash
(develop)$ git checkout solution -- file1.txt
```
这会把这个文件内容从分支 `solution` 拿到分支 `develop` 里来:
```bash
# On branch develop
# Your branch is up-to-date with 'origin/develop'.
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: file1.txt
```
然后, 正常提交。
Note: Spike solutions are made to analyze or solve the problem. These solutions are used for estimation and discarded once everyone gets clear visualization of the problem. \~ [Wikipedia](https://en.wikipedia.org/wiki/Extreme_programming_practices).
### 我把几个提交(commit)提交到了同一个分支,而这些提交应该分布在不同的分支里
假设你有一个`master`分支, 执行`git log`, 你看到你做过两次提交:
```bash
(master)$ git log
commit e3851e817c451cc36f2e6f3049db528415e3c114
Author: Alex Lee <alexlee@example.com>
Date: Tue Jul 22 15:39:27 2014 -0400
Bug #21 - Added CSRF protection
commit 5ea51731d150f7ddc4a365437931cd8be3bf3131
Author: Alex Lee <alexlee@example.com>
Date: Tue Jul 22 15:39:12 2014 -0400
Bug #14 - Fixed spacing on title
commit a13b85e984171c6e2a1729bb061994525f626d14
Author: Aki Rose <akirose@example.com>
Date: Tue Jul 21 01:12:48 2014 -0400
First commit
```
让我们用提交 hash(commit hash)标记 bug (`e3851e8` for #21, `5ea5173` for #14).
首先, 我们把`master`分支重置到正确的提交(`a13b85e`):
```bash
(master)$ git reset --hard a13b85e
HEAD is now at a13b85e
```
现在, 我们对 bug #21 创建一个新的分支:
```bash
(master)$ git checkout -b 21
(21)$
```
接着, 我们用 _cherry-pick_ 把对 bug #21 的提交放入当前分支。 这意味着我们将应用(apply)这个提交(commit),仅仅这一个提交(commit),直接在 HEAD 上面。
```bash
(21)$ git cherry-pick e3851e8
```
这时候, 这里可能会产生冲突, 参见[交互式 rebasing 章](#interactive-rebase) [**冲突节**](#merge-conflict) 解决冲突.
再者, 我们为 bug #14 创建一个新的分支, 也基于`master`分支
```bash
(21)$ git checkout master
(master)$ git checkout -b 14
(14)$
```
最后, 为 bug #14 执行 `cherry-pick`:
```bash
(14)$ git cherry-pick 5ea5173
```
### 我想删除上游(upstream)分支被删除了的本地分支
一旦你在 github 上面合并(merge)了一个 pull request, 你就可以删除你 fork 里被合并的分支。 如果你不准备继续在这个分支里工作, 删除这个分支的本地拷贝会更干净,使你不会陷入工作分支和一堆陈旧分支的混乱之中。
```bash
$ git fetch -p
```
### 我不小心删除了我的分支
如果你定期推送到远程, 多数情况下应该是安全的,但有些时候还是可能删除了还没有推到远程的分支。 让我们先创建一个分支和一个新的文件:
```bash
(master)$ git checkout -b my-branch
(my-branch)$ git branch
(my-branch)$ touch foo.txt
(my-branch)$ ls
README.md foo.txt
```
添加文件并做一次提交
```bash
(my-branch)$ git add .
(my-branch)$ git commit -m 'foo.txt added'
(my-branch)$ foo.txt added
1 files changed, 1 insertions(+)
create mode 100644 foo.txt
(my-branch)$ git log
commit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012
Author: siemiatj <siemiatj@example.com>
Date: Wed Jul 30 00:34:10 2014 +0200
foo.txt added
commit 69204cdf0acbab201619d95ad8295928e7f411d5
Author: Kate Hudson <katehudson@example.com>
Date: Tue Jul 29 13:14:46 2014 -0400
Fixes #6: Force pushing after amending commits
```
现在我们切回到主(master)分支,‘不小心的’删除`my-branch`分支
```bash
(my-branch)$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
(master)$ git branch -D my-branch
Deleted branch my-branch (was 4e3cd85).
(master)$ echo oh noes, deleted my branch!
oh noes, deleted my branch!
```
在这时候你应该想起了`reflog`, 一个升级版的日志,它存储了仓库(repo)里面所有动作的历史。
```
(master)$ git reflog
69204cd HEAD@{0}: checkout: moving from my-branch to master
4e3cd85 HEAD@{1}: commit: foo.txt added
69204cd HEAD@{2}: checkout: moving from master to my-branch
```
正如你所见,我们有一个来自删除分支的提交 hash(commit hash),接下来看看是否能恢复删除了的分支。
```bash
(master)$ git checkout -b my-branch-help
Switched to a new branch 'my-branch-help'
(my-branch-help)$ git reset --hard 4e3cd85
HEAD is now at 4e3cd85 foo.txt added
(my-branch-help)$ ls
README.md foo.txt
```
看! 我们把删除的文件找回来了。 Git 的 `reflog` 在 rebasing 出错的时候也是同样有用的。
### 我想删除一个分支
删除一个远程分支:
```bash
(master)$ git push origin --delete my-branch
```
你也可以:
```bash
(master)$ git push origin :my-branch
```
删除一个本地分支:
```bash
(master)$ git branch -D my-branch
```
### 我想从别人正在工作的远程分支签出(checkout)一个分支
首先, 从远程拉取(fetch) 所有分支:
```bash
(master)$ git fetch --all
```
假设你想要从远程的`daves`分支签出到本地的`daves`
```bash
(master)$ git checkout --track origin/daves
Branch daves set up to track remote branch daves from origin.
Switched to a new branch 'daves'
```
(`--track` 是 `git checkout -b [branch] [remotename]/[branch]` 的简写)
这样就得到了一个`daves`分支的本地拷贝, 任何推过(pushed)的更新,远程都能看到.
## Rebasing 和合并(Merging)
### 我想撤销 rebase/merge
你可以合并(merge)或 rebase 了一个错误的分支, 或者完成不了一个进行中的 rebase/merge。 Git 在进行危险操作的时候会把原始的 HEAD 保存在一个叫 ORIG_HEAD 的变量里, 所以要把分支恢复到 rebase/merge 前的状态是很容易的。
```bash
(my-branch)$ git reset --hard ORIG_HEAD
```
### 我已经 rebase 过, 但是我不想强推(force push)
不幸的是,如果你想把这些变化(changes)反应到远程分支上,你就必须得强推(force push)。 是因你快进(Fast forward)了提交,改变了 Git 历史, 远程分支不会接受变化(changes),除非强推(force push)。这就是许多人使用 merge 工作流, 而不是 rebasing 工作流的主要原因之一, 开发者的强推(force push)会使大的团队陷入麻烦。使用时需要注意,一种安全使用 rebase 的方法是,不要把你的变化(changes)反映到远程分支上, 而是按下面的做:
```bash
(master)$ git checkout my-branch
(my-branch)$ git rebase -i master
(my-branch)$ git checkout master
(master)$ git merge --ff-only my-branch
```
更多, 参见 [this SO thread](http://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push).
### 我需要组合(combine)几个提交(commit)
假设你的工作分支将会做对于 `master` 的 pull-request。 一般情况下你不关心提交(commit)的时间戳,只想组合 _所有_ 提交(commit) 到一个单独的里面, 然后重置(reset)重提交(recommit)。 确保主(master)分支是最新的和你的变化都已经提交了, 然后:
```bash
(my-branch)$ git reset --soft master
(my-branch)$ git commit -am "New awesome feature"
```
如果你想要更多的控制, 想要保留时间戳, 你需要做交互式 rebase (interactive rebase):
```bash
(my-branch)$ git rebase -i master
```
如果没有相对的其它分支, 你将不得不相对自己的`HEAD` 进行 rebase。 例如:你想组合最近的两次提交(commit), 你将相对于`HEAD\~2` 进行 rebase 组合最近 3 次提交(commit), 相对于`HEAD\~3`, 等等。
```bash
(master)$ git rebase -i HEAD~2
```
在你执行了交互式 rebase 的命令(interactive rebase command)后, 你将在你的编辑器里看到类似下面的内容:
```vim
pick a9c8a1d Some refactoring
pick 01b2fd8 New awesome feature
pick b729ad5 fixup
pick e3851e8 another fix
# Rebase 8074d12..b729ad5 onto 8074d12
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
```
所有以 `#` 开头的行都是注释, 不会影响 rebase.
然后,你可以用任何上面命令列表的命令替换 `pick`, 你也可以通过删除对应的行来删除一个提交(commit)。
例如, 如果你想 **单独保留最旧(first)的提交(commit),组合所有剩下的到第二个里面**, 你就应该编辑第二个提交(commit)后面的每个提交(commit) 前的单词为 `f`:
```vim
pick a9c8a1d Some refactoring
pick 01b2fd8 New awesome feature
f b729ad5 fixup
f e3851e8 another fix
```
如果你想组合这些提交(commit) **并重命名这个提交(commit)**, 你应该在第二个提交(commit)旁边添加一个`r`,或者更简单的用`s` 替代 `f`:
```vim
pick a9c8a1d Some refactoring
pick 01b2fd8 New awesome feature
s b729ad5 fixup
s e3851e8 another fix
```
你可以在接下来弹出的文本提示框里重命名提交(commit)。
```vim
Newer, awesomer features
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# rebase in progress; onto 8074d12
# You are currently editing a commit while rebasing branch 'master' on '8074d12'.
#
# Changes to be committed:
# modified: README.md
#
```
如果成功了, 你应该看到类似下面的内容:
```bash
(master)$ Successfully rebased and updated refs/heads/master.
```
#### 安全合并(merging)策略
`--no-commit` 执行合并(merge)但不自动提交, 给用户在做提交前检查和修改的机会。 `no-ff` 会为特性分支(feature branch)的存在过留下证据, 保持项目历史一致。
```bash
(master)$ git merge --no-ff --no-commit my-branch
```
#### 我需要将一个分支合并成一个提交(commit)
```bash
(master)$ git merge --squash my-branch
```
#### 我只想组合(combine)未推的提交(unpushed commit)
有时候,在将数据推向上游之前,你有几个正在进行的工作提交(commit)。这时候不希望把已经推(push)过的组合进来,因为其他人可能已经有提交(commit)引用它们了。
```bash
(master)$ git rebase -i @{u}
```
这会产生一次交互式的 rebase(interactive rebase), 只会列出没有推(push)的提交(commit) 在这个列表时进行 reorder/fix/squash 都是安全的。
### 检查是否分支上的所有提交(commit)都合并(merge)过了
检查一个分支上的所有提交(commit)是否都已经合并(merge)到了其它分支, 你应该在这些分支的 head(或任何 commits)之间做一次 diff:
```bash
(master)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll
```
这会告诉你在一个分支里有而另一个分支没有的所有提交(commit), 和分支之间不共享的提交(commit)的列表。 另一个做法可以是:
```bash
(master)$ git log master ^feature/120-on-scroll --no-merges
```
### 交互式 rebase(interactive rebase)可能出现的问题
#### 这个 rebase 编辑屏幕出现'noop'
如果你看到的是这样:
```
noop
```
这意味着你 rebase 的分支和当前分支在同一个提交(commit)上, 或者 _领先(ahead)_ 当前分支。 你可以尝试:
- 检查确保主(master)分支没有问题
- rebase `HEAD\~2` 或者更早
#### 有冲突的情况
如果你不能成功的完成 rebase, 你可能必须要解决冲突。
首先执行 `git status` 找出哪些文件有冲突:
```bash
(my-branch)$ git status
On branch my-branch
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
```
在这个例子里面, `README.md` 有冲突。 打开这个文件找到类似下面的内容:
```vim
<<<<<<< HEAD
some code
=========
some code
>>>>>>> new-commit
```
你需要解决新提交的代码(示例里, 从中间`==`线到`new-commit`的地方)与`HEAD` 之间不一样的地方.
有时候这些合并非常复杂,你应该使用可视化的差异编辑器(visual diff editor):
```bash
(master*)$ git mergetool -t opendiff
```
在你解决完所有冲突和测试过后, `git add` 变化了的(changed)文件, 然后用`git rebase --continue` 继续 rebase。
```bash
(my-branch)$ git add README.md
(my-branch)$ git rebase --continue
```
如果在解决完所有的冲突过后,得到了与提交前一样的结果, 可以执行`git rebase --skip`。
任何时候你想结束整个 rebase 过程,回来 rebase 前的分支状态, 你可以做:
```bash
(my-branch)$ git rebase --abort
```
## 杂项(Miscellaneous Objects)
### 克隆所有子模块
```bash
$ git clone --recursive git://github.com/foo/bar.git
```
如果已经克隆了:
```bash
$ git submodule update --init --recursive
```
### 删除标签(tag)
```bash
$ git tag -d <tag_name>
$ git push <remote> :refs/tags/<tag_name>
```
### 恢复已删除标签(tag)
如果你想恢复一个已删除标签(tag), 可以按照下面的步骤: 首先, 需要找到无法访问的标签(unreachable tag):
```bash
$ git fsck --unreachable | grep tag
```
记下这个标签(tag)的 hash然后用 Git 的 [update-ref](http://git-scm.com/docs/git-update-ref):
```bash
$ git update-ref refs/tags/<tag_name> <hash>
```
这时你的标签(tag)应该已经恢复了。
### 已删除补丁(patch)
如果某人在 GitHub 上给你发了一个 pull request, 但是然后他删除了他自己的原始 fork, 你将没法克隆他们的提交(commit)或使用 `git am`。在这种情况下, 最好手动的查看他们的提交(commit),并把它们拷贝到一个本地新分支,然后做提交。
做完提交后, 再修改作者,参见[变更作者](#commit-wrong-author)。 然后, 应用变化, 再发起一个新的 pull request。
## 跟踪文件(Tracking Files)
### 我只想改变一个文件名字的大小写,而不修改内容
```bash
(master)$ git mv --force myfile MyFile
```
### 我想从 Git 删除一个文件,但保留该文件
```bash
(master)$ git rm --cached log.txt
```
## 配置(Configuration)
### 我想给一些 Git 命令添加别名(alias)
在 OS X 和 Linux 下, 你的 Git 的配置文件储存在 `\~/.gitconfig`。我在`[alias]` 部分添加了一些快捷别名(和一些我容易拼写错误的),如下:
```vim
[alias]
a = add
amend = commit --amend
c = commit
ca = commit --amend
ci = commit -a
co = checkout
d = diff
dc = diff --changed
ds = diff --staged
f = fetch
loll = log --graph --decorate --pretty=oneline --abbrev-commit
m = merge
one = log --pretty=oneline
outstanding = rebase -i @{u}
s = status
unpushed = log @{u}
wc = whatchanged
wip = rebase -i @{u}
zap = fetch -p
```
### 我想缓存一个仓库(repository)的用户名和密码
你可能有一个仓库需要授权,这时你可以缓存用户名和密码,而不用每次推/拉(push/pull)的时候都输入Credential helper 能帮你。
```bash
$ git config --global credential.helper cache
# Set git to use the credential memory cache
```
```bash
$ git config --global credential.helper 'cache --timeout=3600'
# Set the cache to timeout after 1 hour (setting is in seconds)
```
## 我不知道我做错了些什么
你把事情搞砸了:你 `重置(reset)` 了一些东西, 或者你合并了错误的分支, 亦或你强推了后找不到你自己的提交(commit)了。有些时候, 你一直都做得很好, 但你想回到以前的某个状态。
这就是 `git reflog` 的目的, `reflog` 记录对分支顶端(the tip of a branch)的任何改变, 即使那个顶端没有被任何分支或标签引用。基本上, 每次 HEAD 的改变, 一条新的记录就会增加到`reflog`。遗憾的是,这只对本地分支起作用,且它只跟踪动作 (例如,不会跟踪一个没有被记录的文件的任何改变)。
```bash
(master)$ git reflog
0a2e358 HEAD@{0}: reset: moving to HEAD\~2
0254ea7 HEAD@{1}: checkout: moving from 2.2 to master
c10f740 HEAD@{2}: checkout: moving from master to 2.2
```
上面的 reflog 展示了从 master 分支签出(checkout)到 2.2 分支,然后再签回。 那里,还有一个硬重置(hard reset)到一个较旧的提交。最新的动作出现在最上面以 `HEAD@{0}`标识.
如果事实证明你不小心回移(move back)了提交(commit), reflog 会包含你不小心回移前 master 上指向的提交(0254ea7)。
```bash
$ git reset --hard 0254ea7
```
然后使用 git reset 就可以把 master 改回到之前的 commit这提供了一个在历史被意外更改情况下的安全网。
## 资源
- https://github.com/k88hudson/git-flight-rules/blob/master/README_zh-CN.md
- https://github.com/521xueweihan/git-tips

View File

@ -1,252 +0,0 @@
# git-flow 工作流
## 集中式 vs 分布式
在分布式版本控制工具 [**Git**](https://git-scm.com/) 之前,我一直用的是集中式版本控制工具,具体来说,我用过 **[ClearCase](http://www-03.ibm.com/software/products/en/clearcase)**(简称 cc、**[Subversion](https://tortoisesvn.net/)**(简称 svn
这里,结合我的一点个人经验,谈谈这几个工具的特点。
### 集中式版本控制
**[ClearCase](http://www-03.ibm.com/software/products/en/clearcase)** 是 IBM 的产品。IBM 的产品总给人一种过于重型化的感觉,似乎它们的产品什么都想做,结果反而让人觉得太复杂,不好用(想想曾经被 Notes 邮箱支配的恐惧吧)。**[ClearCase](http://www-03.ibm.com/software/products/en/clearcase)** 一如既往,功能复杂,但是操作很繁琐。
**[Subversion](https://tortoisesvn.net/)** 由于 logo 是乌龟所以也常被称为小乌龟。它的优点是GUI 工具做的很细致,易于上手;安全控制和权限控制非常细粒度(目录级别的管控);对于特别大型的项目,每个开发者都拷贝完整的镜像到本地,会占用较大的磁盘空间,还不如将所有数据都存放在大型服务器上。
### 分布式版本控制
分布式版本控制工具当然不止 Git但是受 Github 的影响Git 无疑是最火,用户最广的工具。
Git 的优点主要就体现在分布式设计上:
- 支持离线工作。除了同步远程仓库,基本都是在本地完成工作。
- 安全稳定。集中式版本控制工具,要求所有机器将每次修改都推送到中央服务器,一旦中央服务器宕机,所有人都不能工作。分布式版本控制工具的每台机器克隆远程仓库到本地后,都拥有完整的镜像,一台机器宕机,不影响其他人工作,而且数据容易恢复。
- Git 自身有着优秀的分支模型,拉分支、打标签都非常便捷。
### 小结
**[ClearCase](http://www-03.ibm.com/software/products/en/clearcase)** 比较难用,谁用谁知道。
**[Subversion](https://tortoisesvn.net/)** 由于自身的优点,还是有不少公司仍在使用的。不能说不使用分布式版本控制就一定是 out 了,很多时候也是基于公司应用场景的考量(大公司往往更看重安全和权限控制)。个人认为 svn 还是挺好用的,除了拉分支确实比较麻烦些,但这也是基于 svn 本身权限控制的考虑。
[**Git**](https://git-scm.com/) 由于其开源免费、分布式特性,深受互联网公司的青睐。
## 版本管理的挑战
Git 是一个非常优秀的版本控制工具,但是在实际版本管理中,仍然会遇到一些问题:
1. 如何开始一个Feature的开发而不影响别的Feature
2. 由于很容易创建新分支,分支多了如何管理,时间久了,如何知道每个分支是干什么的?
3. 哪些分支已经合并回了主干?
4. 如何进行Release的管理开始一个Release的时候如何冻结Feature, 如何在Prepare Release的时候开发人员可以继续开发新的功能
5. 线上代码出Bug了如何快速修复而且修复的代码要包含到开发人员的分支以及下一个Release?
大部分开发人员现在使用Git就只是用三个甚至两个分支一个是Master, 一个是Develop, 还有一个是基于Develop打得各种分支。这个在小项目规模的时候还勉强可以支撑因为很多人做项目就只有一个Release, 但是人员一多,而且项目周期一长就会出现各种问题。
## git-flow 模型
[Vincent Driessen](http://nvie.com/about/) 同学发表了博客 [A successful Git branching model](http://nvie.com/git-model) ,文章讲解了他是如何让自己的[Git](http://www.oschina.net/p/git)仓库保持整洁除此之外他发布了git-flow; 一个可以轻松实现该模型的Git扩展。
这个最佳实践已经成为最为流行的 git 分支模型,一些 GUI 工具甚至已经支持建立这种模型。
下面,来介绍一下 git-flow 模型。
<br><div align="center"><img src="http://dunwu.test.upcdn.net/cs/web/git/git-flow.png!zp"/></div><br>
`Gitflow`工作流仍然用中央仓库作为所有开发者的交互中心。和其它的工作流一样,开发者在本地工作并`push`分支到要中央仓库中。
### 核心分支
`Gitflow`工作流使用2个分支来记录项目的历史。
`master` 分支对应线上实际的发布版本。
`develop` 分支作为功能的集成分支。
<br><div align="center"><img src="https://raw.githubusercontent.com/quickhack/translations/master/git-workflows-and-tutorials/images/git-workflow-release-cycle-1historical.png"/></div><br>
### 功能分支
每个新功能位于一个自己的分支,这样可以[`push`到中央仓库以备份和协作](https://www.atlassian.com/git/tutorial/remote-repositories#!push)。但功能分支不是从`master`分支上拉出新分支,而是使用`develop`分支作为父分支。当新功能完成时,[合并回`develop`分支](https://www.atlassian.com/git/tutorial/git-branches#!merge)。新功能提交应该从不直接与`master`分支交互。
<br><div align="center"><img src="https://raw.githubusercontent.com/quickhack/translations/master/git-workflows-and-tutorials/images/git-workflow-release-cycle-2feature.png"/></div><br>
注意,从各种含义和目的上来看,功能分支加上`develop`分支就是功能分支工作流的用法。但`Gitflow`工作流没有在这里止步。
### 发布分支
<br><div align="center"><img src="https://raw.githubusercontent.com/quickhack/translations/master/git-workflows-and-tutorials/images/git-workflow-release-cycle-3release.png"/></div><br>
一旦`develop`分支上有了做一次发布(或者说快到了既定的发布日)的足够功能,就从`develop`分支上`fork`一个发布分支。新建的分支用于开始发布循环,所以从这个时间点开始之后新的功能不能再加到这个分支上 —— 这个分支只应该做`Bug`修复、文档生成和其它面向发布任务。一旦对外发布的工作都完成了,发布分支合并到`master`分支并分配一个版本号打好`Tag`。另外,这些从新建发布分支以来的做的修改要合并回`develop`分支。
使用一个用于发布准备的专门分支,使得一个团队可以在完善当前的发布版本的同时,另一个团队可以继续开发下个版本的功能。
这也打造定义良好的开发阶段比如可以很轻松地说『这周我们要做准备发布版本4.0』,并且在仓库的目录结构中可以实际看到)。
常用的分支约定:
`用于新建发布分支的分支: develop用于合并的分支: master分支命名: release-* 或 release/*`
### 维护分支
<br><div align="center"><img src="https://raw.githubusercontent.com/quickhack/translations/master/git-workflows-and-tutorials/images/git-workflow-release-cycle-4maintenance.png"/></div><br>
维护分支或说是热修复(`hotfix`)分支用于生成快速给产品发布版本(`production releases`)打补丁,这是唯一可以直接从`master`分支`fork`出来的分支。修复完成,修改应该马上合并回`master`分支和`develop`分支(当前的发布分支),`master`分支应该用新的版本号打好`Tag`。
为`Bug`修复使用专门分支,让团队可以处理掉问题而不用打断其它工作或是等待下一个发布循环。你可以把维护分支想成是一个直接在`master`分支上处理的临时发布。
## git-flow 代码示例
a. 创建develop分支
```bash
git branch develop
git push -u origin develop
```
b. 开始新Feature开发
```bash
git checkout -b some-feature develop
# Optionally, push branch to origin:
git push -u origin some-feature
# 做一些改动
git status
git add some-file
git commit
```
c. 完成Feature
```bash
git pull origin develop
git checkout develop
git merge --no-ff some-feature
git push origin develop
git branch -d some-feature
# If you pushed branch to origin:
git push origin --delete some-feature
```
d. 开始Relase
```bash
git checkout -b release-0.1.0 develop
# Optional: Bump version number, commit
# Prepare release, commit
```
e. 完成Release
```bash
git checkout master
git merge --no-ff release-0.1.0
git push
git checkout develop
git merge --no-ff release-0.1.0
git push
git branch -d release-0.1.0
# If you pushed branch to origin:
git push origin --delete release-0.1.0
git tag -a v0.1.0 master
git push --tags
```
f. 开始Hotfix
```bash
git checkout -b hotfix-0.1.1 master
```
g. 完成Hotfix
```bash
git checkout master
git merge --no-ff hotfix-0.1.1
git push
git checkout develop
git merge --no-ff hotfix-0.1.1
git push
git branch -d hotfix-0.1.1
git tag -a v0.1.1 master
git push --tags
```
## git-flow 工具
实际上,当你理解了上面的流程后,你完全不用使用工具,但是实际上我们大部分人很多命令就是记不住呀,流程就是记不住呀,肿么办呢?
总有聪明的人创造好的工具给大家用, 那就是Git flow script.
### git-flow
#### 安装
你需要有一个可以工作的 git 作为前提。
Git flow 可以工作在 OSX, Linux 和 Windows之下
- OSX Homebrew
```
$ brew install git-flow
```
- OSX Macports
```
$ port install git-flow
```
- Linux
```
$ apt-get install git-flow
```
- Windows (Cygwin):
安装 git-flow, 你需要 wget 和 util-linux。
```
$ wget -q -O - --no-check-certificate https://github.com/nvie/gitflow/raw/develop/contrib/gitflow-installer.sh | bash
```
#### 使用
- **初始化:** git flow init
- **开始新Feature:** git flow feature start MYFEATURE
- **Publish一个Feature(也就是push到远程):** git flow feature publish MYFEATURE
- **获取Publish的Feature:** git flow feature pull origin MYFEATURE
- **完成一个Feature:** git flow feature finish MYFEATURE
- **开始一个Release:** git flow release start RELEASE [BASE]
- **Publish一个Release:** git flow release publish RELEASE
- **发布Release:** git flow release finish RELEASE
别忘了git push --tags
- **开始一个Hotfix:** git flow hotfix start VERSION [BASENAME]
- **发布一个Hotfix:** git flow hotfix finish VERSION
<br><div align="center"><img src="http://dunwu.test.upcdn.net/cs/web/git/git-flow-commands.png!zp"/></div><br>
### Source Tree
[Source Tree](https://www.sourcetreeapp.com/) 支持Mac, Windows, Linux是一个不过的 git-flow GUI 工具。
## 资料
[git 官网](https://git-scm.com/) | [git 官方 Github](https://github.com/git/git)
[廖雪峰的 git 教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000)
[https://github.com/arslanbilal/git-cheat-sheet/blob/master/other-sheets/git-cheat-sheet-zh.md](https://github.com/arslanbilal/git-cheat-sheet/blob/master/other-sheets/git-cheat-sheet-zh.md)

View File

@ -1,520 +0,0 @@
# Git 快速指南
## 简介
### Git 是什么?
Git 是一个开源的分布式版本控制系统。
### 什么是版本控制?
版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。
### 什么是分布式版本控制系统?
介绍分布式版本控制系统前,有必要先了解一下传统的集中式版本控制系统。
**集中化的版本控制系统**,诸如 CVSSubversion 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。
这么做最显而易见的缺点是中央服务器的单点故障。如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。要是中央服务器的磁盘发生故障,碰巧没做备份,或者备份不够及时,就会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录。
<br><div align="center"><img src="https://git-scm.com/figures/18333fig0102-tn.png"/></div><br>
**分布式版本控制系统**的客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。因为每一次的提取操作,实际上都是一次对代码仓库的完整备份。
<br><div align="center"><img src="https://git-scm.com/figures/18333fig0103-tn.png"/></div><br>
### 为什么使用 Git
Git 是分布式的。这是 Git 和其它非分布式的版本控制系统,例如 svncvs 等,最核心的区别。分布式带来以下好处:
**工作时不需要联网**
首先,分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件 A你的同事也在他的电脑上改了文件 A这时你们俩之间只需把各自的修改推送给对方就可以互相看到对方的修改了。
**更加安全**
集中式版本控制系统,一旦中央服务器出了问题,所有人都无法工作。
分布式版本控制系统,每个人电脑中都有完整的版本库,所以某人的机器挂了,并不影响其它人。
## 原理
### 版本库
当你一个项目到本地或创建一个 git 项目,项目目录下会有一个隐藏的 `.git` 子目录。这个目录是 git 用来跟踪管理版本库的,千万不要手动修改。
### 哈希值
Git 中所有数据在存储前都计算校验和,然后以校验和来引用。 这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。 这个功能建构在 Git 底层,是构成 Git 哲学不可或缺的部分。 若你在传送过程中丢失信息或损坏文件Git 就能发现。
Git 用以计算校验和的机制叫做 SHA-1 散列hash哈希。 这是一个由 40 个十六进制字符0-9 和 a-f组成字符串基于 Git 中文件的内容或目录结构计算出来。 SHA-1 哈希看起来是这样:
```
24b9da6552252987aa493b52f8696cd6d3b00373
```
Git 中使用这种哈希值的情况很多,你将经常看到这种哈希值。 实际上Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。
### 文件状态
在 GIt 中,你的文件可能会处于三种状态之一:
- **已修改modified**
已修改表示修改了文件,但还没保存到数据库中。
- **已暂存staged**
已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
- **已提交committed**
已提交表示数据已经安全的保存在本地数据库中。
### 工作区域
与文件状态对应的,不同状态的文件在 Git 中处于不同的工作区域。
- **工作区working**
当你 `git clone` 一个项目到本地,相当于在本地克隆了项目的一个副本。
工作区是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。
* **暂存区staging**
暂存区是一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库目录中。 有时候也被称作`‘索引’',不过一般说法还是叫暂存区。
- **本地仓库local**
提交更新,找到暂存区域的文件,将快照永久性存储到 Git 本地仓库。
- **远程仓库remote**
以上几个工作区都是在本地。为了让别人可以看到你的修改,你需要将你的更新推送到远程仓库。
同理,如果你想同步别人的修改,你需要从远程仓库拉取更新。
<br><div align="center"><img src="http://dunwu.test.upcdn.net/cs/web/git/git-theory.png!zp"/></div><br>
## 安装
### Linux
#### Debian/Ubuntu
如果你使用的系统是 Debian/Ubuntu 安装命令为:
```bash
$ apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \
> libz-dev libssl-dev
$ apt-get install git-core
$ git --version
git version 1.8.1.2
```
#### Centos/RedHat
如果你使用的系统是 Centos/RedHat ,安装命令为:
```bash
$ yum install curl-devel expat-devel gettext-devel \
> openssl-devel zlib-devel
$ yum -y install git-core
$ git --version
git version 1.7.1
```
### Windows
在[Git 官方下载地址](https://git-scm.com/downloads)下载 exe 安装包。按照安装向导安装即可。
建议安装 Git Bash 这个 git 的命令行工具。
### Mac
在[Git 官方下载地址](https://git-scm.com/downloads)下载 mac 安装包。按照安装向导安装即可。
## 配置
Git 自带一个 `git config` 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:
1. `/etc/gitconfig` 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果使用带有 `--system` 选项的 `git config` 时,它会从此文件读写配置变量。
2. `\~/.gitconfig``\~/.config/git/config` 文件:只针对当前用户。 可以传递 `--global` 选项让 Git 读写此文件。
3. 当前使用仓库的 Git 目录中的 `config` 文件(就是 `.git/config`):针对该仓库。
每一个级别覆盖上一级别的配置,所以 `.git/config` 的配置变量会覆盖 `/etc/gitconfig` 中的配置变量。
在 Windows 系统中Git 会查找 `$HOME` 目录下(一般情况下是 `C:\Users\$USER`)的 `.gitconfig` 文件。 Git 同样也会寻找 `/etc/gitconfig` 文件,但只限于 MSys 的根目录下,即安装 Git 时所选的目标位置。
### 用户信息
当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址。 这样做很重要,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改:
```
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
```
再次强调,如果使用了 `--global` 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 `--global` 选项的命令来配置。
很多 GUI 工具都会在第一次运行时帮助你配置这些信息。
### .gitignore
`.gitignore` 文件可能从字面含义也不难猜出:这个文件里配置的文件或目录,会自动被 git 所忽略,不纳入版本控制。
在日常开发中,我们的项目经常会产生一些临时文件,如编译 Java 产生的 `*.class` 文件,又或是 IDE 自动生成的隐藏目录Intellij 的 `.idea` 目录、Eclipse 的 `.settings` 目录等)等等。这些文件或目录实在没必要纳入版本管理。在这种场景下,你就需要用到 `.gitignore` 配置来过滤这些文件或目录。
配置的规则很简单,也没什么可说的,看几个例子,自然就明白了。
这里推荐一下 Github 的开源项目https://github.com/github/gitignore
在这里你可以找到很多常用的模板Java、Nodejs、C++ 的 `.gitignore` 模板等等。
## 命令
国外网友制作了一张 Git Cheat Sheet总结很精炼各位不妨收藏一下。
本节选择性介绍 git 中比较常用的命令行场景。
<br><div align="center"><img src="http://dunwu.test.upcdn.net/cs/web/git/git-cheat-sheet.png!zp"/></div><br>
### 创建
#### 克隆一个已创建的仓库
```bash
# 通过 SSH
$ git clone ssh://user@domain.com/repo.git
#通过 HTTP
$ git clone http://domain.com/user/repo.git
```
#### 创建一个新的本地仓库
```bash
$ git init
```
### 添加修改
#### 添加修改到暂存区
```bash
# 把指定文件添加到暂存区
$ git add xxx
# 把当前所有修改添加到暂存区
$ git add .
# 把所有修改添加到暂存区
$ git add -A
```
#### 提交修改到本地仓库
```bash
# 提交本地的所有修改
$ git commit -a
# 提交之前已标记的变化
$ git commit
# 附加消息提交
$ git commit -m 'commit message'
```
#### 储藏
有时,我们需要在同一个项目的不同分支上工作。当需要切换分支时,偏偏本地的工作还没有完成,此时,提交修改显得不严谨,但是不提交代码又无法切换分支。这时,你可以使用 `git stash` 将本地的修改内容作为草稿储藏起来。
官方称之为储藏,但我个人更喜欢称之为存草稿。
```bash
# 1. 将修改作为当前分支的草稿保存
$ git stash
# 2. 查看草稿列表
$ git stash list
stash@{0}: WIP on master: 6fae349 :memo: Writing docs.
# 3.1 删除草稿
$ git stash drop stash@{0}
# 3.2 读取草稿
$ git stash apply stash@{0}
```
### 撤销修改
#### 撤销本地修改
```bash
# 移除缓存区的所有文件i.e. 撤销上次git add
$ git reset HEAD
# 将HEAD重置到上一次提交的版本并将之后的修改标记为未添加到缓存区的修改
$ git reset <commit>
# 将HEAD重置到上一次提交的版本并保留未提交的本地修改
$ git reset --keep <commit>
# 放弃工作目录下的所有修改
$ git reset --hard HEAD
# 将HEAD重置到指定的版本并抛弃该版本之后的所有修改
$ git reset --hard <commit-hash>
# 用远端分支强制覆盖本地分支
$ git reset --hard <remote/branch> e.g., upstream/master, origin/my-feature
# 放弃某个文件的所有本地修改
$ git checkout HEAD <file>
```
##### 删除添加`.gitignore`文件前错误提交的文件
```bash
$ git rm -r --cached .
$ git add .
$ git commit -m "remove xyz file"
```
#### 撤销远程修改
#### 创建一个新的提交,并回滚到指定版本
```bash
$ git revert <commit-hash>
```
#### 彻底删除指定版本
```bash
# 执行下面命令后commit-hash 提交后的记录都会被彻底删除,使用需谨慎
$ git reset --hard <commit-hash>
$ git push -f
```
### 更新与推送
#### 更新
```bash
# 下载远程端版本但不合并到HEAD中
$ git fetch <remote>
# 将远程端版本合并到本地版本中
$ git pull origin master
# 以rebase方式将远端分支与本地合并
$ git pull --rebase <remote> <branch>
```
#### 推送
```bash
# 将本地版本推送到远程端
$ git push remote <remote> <branch>
# 删除远程端分支
$ git push <remote> :<branch> (since Git v1.5.0)
$ git push <remote> --delete <branch> (since Git v1.7.0)
# 发布标签
$ git push --tags
```
### 查看信息
#### 显示工作路径下已修改的文件
```bash
$ git status
```
#### 显示与上次提交版本文件的不同
```bash
$ git diff
```
#### 显示提交历史
```bash
# 从最新提交开始显示所有的提交记录显示hash 作者信息,提交的标题和时间)
$ git log
# 显示某个用户的所有提交
$ git log --author="username"
# 显示某个文件的所有修改
$ git log -p <file>
```
#### 显示搜索内容
```bash
# 从当前目录的所有文件中查找文本内容
$ git grep "Hello"
# 在某一版本中搜索文本
$ git grep "Hello" v2.5
```
### 分支与标签
#### 增删查分支
```bash
# 列出所有的分支
$ git branch
# 列出所有的远端分支
$ git branch -r
# 基于当前分支创建新分支
$ git branch <new-branch>
# 基于远程分支创建新的可追溯的分支
$ git branch --track <new-branch> <remote-branch>
# 删除本地分支
$ git branch -d <branch>
# 强制删除本地分支,将会丢失未合并的修改
$ git branch -D <branch>
```
#### 切换分支
```bash
# 切换分支
$ git checkout <branch>
# 创建并切换到新分支
$ git checkout -b <branch>
```
#### 标签
```bash
# 给当前版本打标签
$ git tag <tag-name>
# 给当前版本打标签并附加消息
$ git tag -a <tag-name>
```
### 合并与重置
> merge 与 rebase 虽然是 git 常用功能,但是强烈建议不要使用 git 命令来完成这项工作。
>
> 因为如果出现代码冲突,在没有代码比对工具的情况下,实在太艰难了。
>
> 你可以考虑使用各种 Git GUI 工具。
#### 合并
```bash
# 将分支合并到当前HEAD中
$ git merge <branch>
```
#### 重置
```bash
# 将当前HEAD版本重置到分支中请勿重置已发布的提交
$ git rebase <branch>
```
### Github
Github 作为最著名的代码开源协作社区,在程序员圈想必无人不知,无人不晓。
这里不赘述 Github 的用法确实有不会用的新手同学可以参考官方教程https://guides.github.com/
#### clone 方式
Git 支持三种协议HTTPS / SSH / GIT
而 Github 上支持 HTTPS 和 SSH。
HTTPS 这种方式要求你每次 push 时都要输入用户名、密码,有些繁琐。
而 SSH 要求你本地生成证书,然后在你的 Github 账户中注册。第一次配置麻烦是麻烦了点,但是以后就免去了每次 push 需要输入用户名、密码的繁琐。
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-66f60822aeb2c21c.png"/></div><br>
以下介绍以下,如何生成证书,以及在 Github 中注册。
#### 生成 SSH 公钥
如前所述,许多 Git 服务器都使用 SSH 公钥进行认证。 为了向 Git 服务器提供 SSH 公钥,如果某系统用户尚未拥有密钥,必须事先为其生成一份。 这个过程在所有操作系统上都是相似的。 首先,你需要确认自己是否已经拥有密钥。 默认情况下,用户的 SSH 密钥存储在其 `\~/.ssh` 目录下。 进入该目录并列出其中内容,你便可以快速确认自己是否已拥有密钥:
```
$ cd ~/.ssh
$ ls
authorized_keys2 id_dsa known_hosts
config id_dsa.pub
```
我们需要寻找一对以 `id_dsa``id_rsa` 命名的文件,其中一个带有 `.pub` 扩展名。 `.pub` 文件是你的公钥,另一个则是私钥。 如果找不到这样的文件(或者根本没有 `.ssh` 目录),你可以通过运行 `ssh-keygen` 程序来创建它们。在 Linux/Mac 系统中,`ssh-keygen` 随 SSH 软件包提供;在 Windows 上,该程序包含于 MSysGit 软件包中。
```
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/schacon/.ssh/id_rsa):
Created directory '/home/schacon/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/schacon/.ssh/id_rsa.
Your public key has been saved in /home/schacon/.ssh/id_rsa.pub.
The key fingerprint is:
d0:82:24:8e:d7:f1:bb:9b:33:53:96:93:49:da:9b:e3 schacon@mylaptop.local
```
首先 `ssh-keygen` 会确认密钥的存储位置(默认是 `.ssh/id_rsa`),然后它会要求你输入两次密钥口令。如果你不想在使用密钥时输入口令,将其留空即可。
现在,进行了上述操作的用户需要将各自的公钥发送给任意一个 Git 服务器管理员(假设服务器正在使用基于公钥的 SSH 验证设置)。 他们所要做的就是复制各自的 `.pub` 文件内容,并将其通过邮件发送。 公钥看起来是这样的:
```
$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx
NrRFi9wrf+M7Q== schacon@mylaptop.local
```
在你的 Github 账户中,依次点击 **Settings** > **SSH and GPG keys** > **New SSH key**
然后,将上面生成的公钥内容粘贴到 `Key` 编辑框并保存。至此大功告成。
后面,你在克隆你的 Github 项目时使用 SSH 方式即可。
<br><div align="center"><img src="https://help.github.chttps://raw.githubusercontent.com/dunwu/design/master/images/refactor/help/settings/ssh-key-paste.png"/></div><br>
如果觉得我的讲解还不够细致可以参考https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/
## 小结
最后,放一张我总结的脑图总结一下以上的知识点。
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-2044cc669d78eef9.png"/></div><br>
## 资料
[git 官网](https://git-scm.com/) | [git 官方 Github](https://github.com/git/git)
[廖雪峰的 git 教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000)
[git-cheat-sheet](https://github.com/arslanbilal/git-cheat-sheet)
[github-cheat-sheet](https://github.com/tiimgreen/github-cheat-sheet)
[Github gitignore 模板](https://github.com/github/gitignore)

Binary file not shown.

Binary file not shown.

View File

@ -1,257 +1,290 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>linux-tutorial</title> <title>Linux Tutorial</title>
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible" /> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible" />
<meta content="linux-tutorial" name="description" /> <meta content="Linux Tutorial" name="description" />
<meta <meta
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
name="viewport" name="viewport"
/> />
<link href="http://dunwu.test.upcdn.net/common/logo/zp_50_50.png" rel="icon" type="image/x-icon" /> <link href="http://dunwu.test.upcdn.net/common/logo/zp_50_50.png" rel="icon" type="image/x-icon" />
<link href="//unpkg.com/docsify/lib/themes/vue.css" rel="stylesheet" title="vue" /> <link href="//unpkg.com/docsify/lib/themes/vue.css" rel="stylesheet" title="vue" />
<style> <style>
h1 + ul { h1 + ul {
display: block !important; display: block !important;
}
.content img,
.sidebar img {
border: none;
border-radius: 8px;
box-shadow: 0 0 8px grey;
}
.content,
.sidebar,
.sidebar-toggle,
body,
.search input {
color: #6B615F !important;
background-color: #FFF4E6 !important;
}
.content strong,
.sidebar strong,
body strong {
color: #5C5869 !important;
}
</style>
<style>
.cover-main .anchor span {
text-align: center;
background-image: -webkit-linear-gradient(left, #FFDCB4, #B96972 25%, #E88A57 50%, #804170 75%, #A596CD);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
-webkit-background-size: 200% 100%;
-webkit-animation: masked-animation 1.5s infinite linear;
font-family: "Brush Script MT", 隶书, serif;
font-weight: 600;
}
.cover-main blockquote p {
color: #5C5869;
font-family: "Arial", 隶书, serif;
}
.cover-main ul a:hover {
color: #FE4165 !important;
}
.cover-main p a:hover {
text-align: center;
background-image: -webkit-linear-gradient(left, #FFDCB4, #B96972 25%, #E88A57 50%, #804170 75%, #A596CD);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
-webkit-background-size: 200% 100%;
-webkit-animation: masked-animation 1.5s infinite linear;
}
/* content 样式内容 */
.sidebar a,
.content a {
color: #399AB2 !important;
text-decoration: none !important;
}
.sidebar a:hover,
.content a:hover {
color: #FE4165 !important;
text-decoration: underline !important;
}
.content h1 :hover,
.content h2 :hover,
.content h3 :hover,
.content h4 :hover {
text-align: center;
background-image: -webkit-linear-gradient(left, #FFDCB4, #B96972 25%, #E88A57 50%, #804170 75%, #A596CD);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
-webkit-background-size: 200% 100%;
-webkit-animation: masked-animation 1.5s infinite linear;
font-family: "微软雅黑", serif;
font-weight: bold;
}
@-webkit-keyframes masked-animation {
0% {
background-position: 0 0;
}
100% {
background-position: -100% 0;
}
}
.content h1 a,
.content h1 span {
color: #399AB2 !important;
font-size: 30px;
text-shadow: 2px 2px 5px grey;
}
.content h2 a,
.content h2 span {
color: #60497C !important;
font-size: 26px;
text-shadow: 2px 2px 5px grey;
}
.content h3 a,
.content h3 span {
color: #346093 !important;
font-size: 22px;
text-shadow: 2px 2px 5px grey;
}
.content h4 a,
.content h4 span {
font-size: 18px;
color: #78943A;
text-shadow: 2px 2px 5px grey;
}
</style>
<style>
.markdown-section h1 {
font-size: 1rem;
margin: 0;
}
.markdown-section h2 {
font-size: 1rem;
margin: 1rem 0px;
}
.markdown-section h3 {
font-size: 1rem;
margin: 0;
}
.markdown-section p {
line-height: 1rem;
word-spacing: 0.05rem;
}
</style>
<style>
.content > p {
font-size: 16px !important;
line-height: 24px;
}
.content blockquote {
display: block;
border-left: 8px solid lightgrey;
padding-right: 8px;
background: #FFF2C9;
overflow: auto;
}
.content pre {
padding-left: 0 !important;
padding-right: 0 !important;
border-radius: 8px;
box-shadow: 1px 1px 20px 3px #DDDDDD !important;
}
.content code {
background-color: white;
box-shadow: 1px 1px 1px lightgrey;
}
.content table {
display: table;
padding-left: 0 !important;
padding-right: 0 !important;
box-shadow: 2px 2px 20px 6px lightgrey !important;
}
.content th {
font-weight: bold;
font-size: 16px;
background-color: #CCE6B6;
}
</style>
<style>
@media (min-width: 600px) {
.markdown-section pre > code {
font-size: 0.9rem !important;
}
}
@media (max-width: 600px) {
.markdown-section pre > code {
padding-top: 5px;
padding-bottom: 5px;
} }
pre:after { .content img,
content: "" !important; .sidebar img {
border: none;
border-radius: 4px;
box-shadow: 2px 2px 5px grey;
} }
}
@media (min-width: 600px) { body,
pre code { .content,
padding-left: 20px !important; .sidebar,
.sidebar-toggle,
.search input {
color: #6b615f !important;
background-color: #fff4e6 !important;
} }
}
@media (max-width: 600px) { body strong,
pre { .content strong,
padding-left: 0px !important; .sidebar strong {
padding-right: 0px !important; color: #5c5869 !important;
}
</style>
<style>
.cover-main .anchor span {
text-align: center;
background-image: -webkit-linear-gradient(left, #ffdcb4, #b96972 25%, #e88a57 50%, #804170 75%, #a596cd);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
-webkit-background-size: 200% 100%;
-webkit-animation: masked-animation 1.5s infinite linear;
font-family: 'Brush Script MT', 隶书, serif;
font-weight: 600;
} }
}
</style>
</head>
<body>
<div id="app">正在加载...</div>
<script>
window.$docsify = {
name: 'linux-tutorial',
repo: 'https://github.com/dunwu/linux-tutorial',
logo: 'http://dunwu.test.upcdn.net/common/logo/zp_100_100.png',
auto2top: true,
coverpage: 'coverpage.md',
maxLevel: 4,
subMaxLevel: 4,
formatUpdated: '{MM}/{DD} {HH}:{mm}',
search: {
maxAge: 86400000, paths: ['/'], placeholder: '🔍 搜索', noData: '没有结果!', depth: 4
}
}
</script>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/emoji.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/zoom-image.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.js"></script>
<!--代码高亮--> .cover-main blockquote p {
<!--@see https://github.com/PrismJS/prism --> color: #5c5869;
<script src="//unpkg.com/prismjs/components/prism-basic.min.js"></script> font-family: 'Arial', 隶书, serif;
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script> }
<script src="//unpkg.com/prismjs/components/prism-java.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-markdown.min.js"></script> .cover-main ul a:hover {
</body> color: #fe4165 !important;
}
.cover-main a:hover {
text-align: center;
background-image: -webkit-linear-gradient(left, #ffdcb4, #b96972 25%, #e88a57 50%, #804170 75%, #a596cd);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
-webkit-background-size: 200% 100%;
-webkit-animation: masked-animation 1.5s infinite linear;
}
/* content 样式内容 */
.content a,
.sidebar a,
.sidebar ul li a,
.sidebar ul li a strong {
color: #399ab2 !important;
text-decoration: none !important;
}
.content a:hover,
.sidebar a:hover,
.sidebar ul li a:hover,
.sidebar ul li a strong:hover {
color: #fe4165 !important;
text-decoration: underline !important;
}
.sidebar h2 span {
font-size: 18px;
color: #399ab2 !important;
text-decoration: none !important;
}
.sidebar h2 span:hover {
color: #fe4165 !important;
text-decoration: underline !important;
}
.sidebar .sidebar-nav {
padding-left: 20px;
}
.content h1 :hover,
.content h2 :hover,
.content h3 :hover,
.content h4 :hover {
text-align: center;
background-image: -webkit-linear-gradient(left, #ffdcb4, #b96972 25%, #e88a57 50%, #804170 75%, #a596cd);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
-webkit-background-size: 200% 100%;
-webkit-animation: masked-animation 1.5s infinite linear;
font-family: '微软雅黑', serif;
font-weight: bold;
}
@-webkit-keyframes masked-animation {
0% {
background-position: 0 0;
}
100% {
background-position: -100% 0;
}
}
.markdown-section h1,
.content h1 a,
.content h1 span {
color: #399ab2 !important;
font-size: 30px;
text-shadow: 2px 2px 5px grey;
}
.content h2 a,
.content h2 span {
color: #60497c !important;
font-size: 26px;
text-shadow: 2px 2px 5px grey;
}
.content h3 a,
.content h3 span {
color: #346093 !important;
font-size: 22px;
text-shadow: 2px 2px 5px grey;
}
.content h4 a,
.content h4 span {
font-size: 18px;
color: #78943a;
text-shadow: 2px 2px 5px grey;
}
</style>
<style>
.markdown-section h1 {
font-size: 1rem;
margin: 0;
}
.markdown-section h2 {
font-size: 1rem;
margin: 1rem 0px;
}
.markdown-section h3 {
font-size: 1rem;
margin: 0;
}
.markdown-section p {
line-height: 1rem;
word-spacing: 0.05rem;
}
</style>
<style>
.content > p {
font-size: 16px !important;
line-height: 24px;
}
.content blockquote {
display: block;
padding: 0 16px;
border-left: 8px solid #dddfe4;
background: #fff2c9;
overflow: auto;
}
.content pre {
padding-left: 0 !important;
padding-right: 0 !important;
border-radius: 8px;
box-shadow: 1px 1px 20px 3px #dddddd !important;
}
.content code {
background-color: white;
box-shadow: 1px 1px 1px lightgrey;
}
.content table {
display: table;
padding-left: 0 !important;
padding-right: 0 !important;
box-shadow: 2px 2px 20px 6px lightgrey !important;
}
.content th {
font-weight: bold;
font-size: 16px;
background-color: #cce6b6;
}
</style>
<style>
@media (min-width: 600px) {
.markdown-section pre > code {
font-size: 0.9rem !important;
}
}
@media (max-width: 600px) {
.markdown-section pre > code {
padding-top: 5px;
padding-bottom: 5px;
}
pre:after {
content: '' !important;
}
}
@media (min-width: 600px) {
pre code {
padding-left: 20px !important;
}
}
@media (max-width: 600px) {
pre {
padding-left: 0 !important;
padding-right: 0 !important;
}
}
</style>
</head>
<body>
<div id="app">正在加载...</div>
<script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
<script src="//unpkg.com/docsify-edit-on-github/index.js"></script>
<script>
window.$docsify = {
name: 'linux-tutorial',
repo: 'https://github.com/dunwu/linux-tutorial',
logo: 'http://dunwu.test.upcdn.net/common/logo/zp_100_100.png',
auto2top: true,
coverpage: 'coverpage.md',
loadSidebar: 'sidebar.md',
maxLevel: 4,
subMaxLevel: 2,
formatUpdated: '{MM}/{DD} {HH}:{mm}',
search: {
maxAge: 86400000,
paths: ['/'],
placeholder: '🔍 搜索',
noData: '😭 没有结果!',
depth: 4
},
disqus: 'linux-tutorial',
plugins: [
EditOnGithubPlugin.create('https://github.com/dunwu/linux-tutorial/tree/master/docs/', null, function(file) {
if (file.indexOf('en') === -1) {
return '📝 编辑文档'
} else {
return '📝 Edit Document'
}
})
]
}
</script>
<script src="//unpkg.com/docsify/lib/plugins/disqus.min.js"></script>
<script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
<!--代码高亮-->
<!--@see https://github.com/PrismJS/prism -->
<script src="//unpkg.com/prismjs/components/prism-basic.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-bash.min.js"></script>
<script src="//unpkg.com/prismjs/components/prism-markdown.min.js"></script>
</body>
</html> </html>

View File

@ -1,898 +0,0 @@
---
title: Python
date: 2018-06-28
categories:
- linux
tags:
- linux
- python
---
# Python
<!-- TOC depthFrom:2 depthTo:3 -->
- [解释器](#解释器)
- [注释](#注释)
- [数据类型](#数据类型)
- [操作符](#操作符)
- [算术运算符](#算术运算符)
- [比较运算符](#比较运算符)
- [赋值运算符](#赋值运算符)
- [位运算符](#位运算符)
- [逻辑运算符](#逻辑运算符)
- [成员运算符](#成员运算符)
- [身份运算符](#身份运算符)
- [运算符优先级](#运算符优先级)
- [控制语句](#控制语句)
- [条件语句](#条件语句)
- [循环语句](#循环语句)
- [函数](#函数)
- [函数变量作用域](#函数变量作用域)
- [关键字参数](#关键字参数)
- [可变参数列表](#可变参数列表)
- [返回值](#返回值)
- [异常](#异常)
- [异常处理](#异常处理)
- [抛出异常](#抛出异常)
- [自定义异常](#自定义异常)
- [面向对象](#面向对象)
- [面向对象技术简介](#面向对象技术简介)
- [类定义](#类定义)
- [类对象](#类对象)
- [类的方法](#类的方法)
- [继承](#继承)
- [多继承](#多继承)
- [方法重写](#方法重写)
- [类属性与方法](#类属性与方法)
- [标准库概览](#标准库概览)
- [操作系统接口](#操作系统接口)
- [文件通配符](#文件通配符)
- [命令行参数](#命令行参数)
- [错误输出重定向和程序终止](#错误输出重定向和程序终止)
- [字符串正则匹配](#字符串正则匹配)
- [数学](#数学)
<!-- /TOC -->
# Python 编程
## 解释器
Linux/Unix 的系统上Python 解释器通常被安装在 `/usr/local/bin/python3.4` 这样的有效路径(目录)里。
我们可以将路径 `/usr/local/bin` 添加到您的 Linux/Unix 操作系统的环境变量中,这样您就可以通过 shell 终端输入下面的命令来启动 Python 。
在 Linux/Unix 系统中,你可以在脚本顶部添加以下命令让 Python 脚本可以像 SHELL 脚本一样可直接执行:
```python
#! /usr/bin/env python3.4
```
## 注释
Python 中的注释有三种形式:
- 以 `#` 开头
- 以 `'''` 开始,以 `'''` 结尾
- 以 `"""` 开始,以 `"""` 结尾
```python
# 单行注释
'''
这是多行注释,用三个单引号
这是多行注释,用三个单引号
这是多行注释,用三个单引号
'''
"""
这是多行注释,用三个双引号
这是多行注释,用三个双引号
这是多行注释,用三个双引号
"""
```
## 数据类型
Python3 中有六个标准的数据类型:
- Numbers数字
- String字符串
- List列表
- Tuple元组
- Sets集合
- Dictionaries字典
## 操作符
Python 语言支持以下类型的运算符:
- 算术运算符
- 比较(关系)运算符
- 赋值运算符
- 逻辑运算符
- 位运算符
- 成员运算符
- 身份运算符
- 运算符优先级
### 算术运算符
| 运算符 | 描述 | 实例 |
| ------ | ----------------------------------------------- | --------------------------------------- |
| + | 加 - 两个对象相加 | a + b 输出结果 31 |
| - | 减 - 得到负数或是一个数减去另一个数 | a - b 输出结果 -11 |
| \* | 乘 - 两个数相乘或是返回一个被重复若干次的字符串 | a \* b 输出结果 210 |
| / | 除 - x 除以 y | b / a 输出结果 2.1 |
| % | 取模 - 返回除法的余数 | b % a 输出结果 1 |
| \*\* | 幂 - 返回 x 的 y 次幂 | a\*\*b 为 10 的 21 次方 |
| // | 取整除 - 返回商的整数部分 | 9//2 输出结果 4 , 9.0//2.0 输出结果 4.0 |
### 比较运算符
| 运算符 | 描述 | 实例 |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
| == | 等于 - 比较对象是否相等 | (a == b) 返回 False。 |
| != | 不等于 - 比较两个对象是否不相等 | (a != b) 返回 True. |
| > | 大于 - 返回 x 是否大于 y | (a > b) 返回 False。 |
| < | 小于 - 返回 x 是否小于 y。所有比较运算符返回 1 表示真,返回 0 表示假。这分别与特殊的变量 True 和 False 等价。注意,这些变量名的大写。 | (a < b) True |
| >= | 大于等于 - 返回 x 是否大于等于 y。 | (a >= b) 返回 False。 |
| <= | 小于等于 - 返回 x 是否小于等于 y。 | (a <= b) 返回 True。 |
### 赋值运算符
| 运算符 | 描述 | 实例 |
| ------ | ---------------- | ------------------------------------- |
| = | 简单的赋值运算符 | c = a + b 将 a + b 的运算结果赋值为 c |
| += | 加法赋值运算符 | c += a 等效于 c = c + a |
| -= | 减法赋值运算符 | c -= a 等效于 c = c - a |
| \*= | 乘法赋值运算符 | c _= a 等效于 c = c _ a |
| /= | 除法赋值运算符 | c /= a 等效于 c = c / a |
| %= | 取模赋值运算符 | c %= a 等效于 c = c % a |
| \*\*= | 幂赋值运算符 | c **= a 等效于 c = c ** a |
| //= | 取整除赋值运算符 | c //= a 等效于 c = c // a |
### 位运算符
| 运算符 | 描述 | 实例 |
| ------ | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
| & | 按位与运算符:参与运算的两个值,如果两个相应位都为 1,则该位的结果为 1,否则为 0 | (a & b) 输出结果 12 ,二进制解释: 0000 1100 |
| \| | 按位或运算符:只要对应的二个二进位有一个为 1 时,结果位就为 1。 | (a \| b) 输出结果 61 ,二进制解释: 0011 1101 |
| ^ | 按位异或运算符:当两对应的二进位相异时,结果为 1 | (a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
| \~ | 按位取反运算符:对数据的每个二进制位取反,即把 1 变为 0,把 0 变为 1 | (\~a ) 输出结果 -61 ,二进制解释: 1100 0011 在一个有符号二进制数的补码形式。 |
| << | 左移动运算符:运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补 0。 | a << 2 240 1111 0000 |
| >> | 右移动运算符:把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数 | a >> 2 输出结果 15 ,二进制解释: 0000 1111 |
### 逻辑运算符
| 运算符 | 逻辑表达式 | 描述 | 实例 |
| ------ | ---------- | ----------------------------------------------------------------------- | ----------------------- |
| and | x and y | 布尔"与" - 如果 x 为 Falsex and y 返回 False否则它返回 y 的计算值。 | (a and b) 返回 20。 |
| or | x or y | 布尔"或" - 如果 x 是 True它返回 x 的值,否则它返回 y 的计算值。 | (a or b) 返回 10。 |
| not | not x | 布尔"非" - 如果 x 为 True返回 False 。如果 x 为 False它返回 True。 | not(a and b) 返回 False |
### 成员运算符
| 运算符 | 描述 | 实例 |
| ------ | ------------------------------------------------------- | ------------------------------------------------- |
| in | 如果在指定的序列中找到值返回 True否则返回 False。 | x 在 y 序列中 , 如果 x 在 y 序列中返回 True。 |
| not in | 如果在指定的序列中没有找到值返回 True否则返回 False。 | x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True。 |
### 身份运算符
| 运算符 | 描述 | 实例 |
| ------ | ------------------------------------------- | ---------------------------------------------------------- |
| is | is 是判断两个标识符是不是引用自一个对象 | x is y, 如果 id(x) 等于 id(y) , **is** 返回结果 1 |
| is not | is not 是判断两个标识符是不是引用自不同对象 | x is not y, 如果 id(x) 不等于 id(y). **is not** 返回结果 1 |
### 运算符优先级
| 运算符 | 描述 |
| --------------------------- | ------------------------------------------------------ |
| \*\* | 指数 (最高优先级) |
| \~ + - | 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) |
| \* / % // | 乘,除,取模和取整除 |
| + - | 加法减法 |
| >> << | 右移,左移运算符 |
| & | 位 'AND' |
| ^ \| | 位运算符 |
| <= < > >= | 比较运算符 |
| <> == != | 等于运算符 |
| = %= /= //= -= += \*= \*\*= | 赋值运算符 |
| is is not | 身份运算符 |
| in not in | 成员运算符 |
| not or and | 逻辑运算符 |
## 控制语句
### 条件语句
```python
if condition_1:
statement_block_1
elif condition_2:
statement_block_2
else:
statement_block_3
```
### 循环语句
#### while
```python
while 判断条件:
statements
```
#### for
```python
for <variable> in <sequence>:
<statements>
```
#### range()
```python
for i in range(0, 10, 3) :
print(i)
```
#### break 和 continue
- break 语句可以跳出 for 和 while 的循环体。
- continue 语句被用来告诉 Python 跳过当前循环块中的剩余语句,然后继续进行下一轮循环。
#### pass
pass 语句什么都不做。它只在语法上需要一条语句但程序不需要任何操作时使用.例如:
```python
while True:
pass # 等待键盘中断 (Ctrl+C)
```
## 函数
Python 定义函数使用 def 关键字,一般格式如下:
```python
def 函数名(参数列表):
函数体
```
### 函数变量作用域
```python
#!/usr/bin/env python3
a = 4 # 全局变量
def print_func1():
a = 17 # 局部变量
print("in print_func a = ", a)
def print_func2():
print("in print_func a = ", a)
print_func1()
print_func2()
print("a = ", a)
```
以上实例运行结果如下:
```python
in print_func a = 17
in print_func a = 4
a = 4
```
### 关键字参数
函数也可以使用 kwarg=value 的关键字参数形式被调用.例如,以下函数:
```python
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")
```
可以以下几种方式被调用:
```python
parrot(1000) # 1 positional argument
parrot(voltage=1000) # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump') # 3 positional arguments
parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword
```
以下为错误调用方法:
```
parrot() # required argument missing
parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument
parrot(110, voltage=220) # duplicate value for the same argument
parrot(actor='John Cleese') # unknown keyword argument
```
### 可变参数列表
最后,一个最不常用的选择是可以让函数调用可变个数的参数.这些参数被包装进一个元组(查看元组和序列).在这些可变个数的参数之前,可以有零到多个普通的参数:
```python
def arithmetic_mean(*args):
sum = 0
for x in args:
sum += x
return sum
```
### 返回值
Python 的函数的返回值使用 return 语句,可以将函数作为一个值赋值给指定变量:
```python
def return_sum(x,y):
c = x + y
return c
```
## 异常
### 异常处理
try 语句按照如下方式工作;
- 首先,执行 try 子句(在关键字 try 和关键字 except 之间的语句)
- 如果没有异常发生,忽略 except 子句try 子句执行后结束。
- 如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行。最后执行 try 语句之后的代码。
- 如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中。
- 不管 try 子句里面有没有发生异常finally 子句都会执行。
```python
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
finally:
# 清理行为
```
### 抛出异常
Python 使用 raise 语句抛出一个指定的异常。例如:
```python
>>> raise NameError('HiThere')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: HiThere
```
### 自定义异常
可以通过创建一个新的 exception 类来拥有自己的异常。异常应该继承自 Exception 类,或者直接继承,或者间接继承。
当创建一个模块有可能抛出多种不同的异常时,一种通常的做法是为这个包建立一个基础异常类,然后基于这个基础类为不同的错误情况创建不同的子类:
```python
class Error(Exception):
"""Base class for exceptions in this module."""
pass
class InputError(Error):
"""Exception raised for errors in the input.
Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""
def __init__(self, expression, message):
self.expression = expression
self.message = message
class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.
Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""
def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message
```
大多数的异常的名字都以"Error"结尾,就跟标准的异常命名一样。
## 面向对象
### 面向对象技术简介
- **类(Class):** 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- **类变量:**类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- **数据成员:**类变量或者实例变量用于处理类及其实例对象的相关的数据。
- **方法重写:**如果从父类继承的方法不能满足子类的需求可以对其进行改写这个过程叫方法的覆盖override也称为方法的重写。
- **实例变量:**定义在方法中的变量,只作用于当前实例的类。
- **继承:**即一个派生类derived class继承基类base class的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如有这样一个设计一个 Dog 类型的对象派生自 Animal 类,这是模拟"是一个is-a"关系例图Dog 是一个 Animal
- **实例化:**创建一个类的实例,类的具体对象。
- **方法:**类中定义的函数。
- **对象:**通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
### 类定义
语法格式如下:
```python
class ClassName:
<statement-1>
.
.
.
<statement-N>
```
类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。
### 类对象
类对象支持两种操作:属性引用和实例化。
属性引用使用和 Python 中所有的属性引用一样的标准语法:**obj.name**。
类对象创建后,类命名空间中所有的命名都是有效属性名。所以如果类定义是这样:
```python
#!/usr/bin/python3
class MyClass:
"""一个简单的类实例"""
i = 12345
def f(self):
return 'hello world'
# 实例化类
x = MyClass()
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i)
print("MyClass 类的方法 f 输出为:", x.f())
```
实例化类:
```python
# 实例化类
x = MyClass()
# 访问类的属性和方法
```
以上创建了一个新的类实例并将该对象赋给局部变量 xx 为空的对象。
执行以上程序输出结果为:
```
MyClass 类的属性 i 为: 12345
MyClass 类的方法 f 输出为: hello world
```
很多类都倾向于将对象创建为有初始状态的。因此类可能会定义一个名为 **init**() 的特殊方法(构造方法),像下面这样:
```python
def __init__(self):
self.data = []
```
类定义了 **init**() 方法的话,类的实例化操作会自动调用 **init**() 方法。所以在下例中,可以这样创建一个新的实例:
```python
x = MyClass()
```
当然, **init**() 方法可以有参数,参数通过 **init**() 传递到类的实例化操作上。例如:
```python
>>> class Complex:
... def __init__(self, realpart, imagpart):
... self.r = realpart
... self.i = imagpart
...
>>> x = Complex(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)
```
### 类的方法
在类地内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数:
```python
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
# 实例化类
p = people('W3Cschool',10,30)
p.speak()
```
执行以上程序输出结果为:
```
W3Cschool 说: 我 10 岁。
```
### 继承
Python 同样支持类的继承,如果一种语言不支持继承就,类就没有什么意义。派生类的定义如下所示:
```python
class DerivedClassName(BaseClassName1):
<statement-1>
.
.
.
<statement-N>
```
需要注意圆括号中基类的顺序若是基类中有相同的方法名而在子类使用时未指定python 从左至右搜索 即方法在子类中未找到时,从左到右查找基类中是否包含方法。
BaseClassName示例中的基类名必须与派生类定义在一个作用域内。除了类还可以用表达式基类定义在另一个模块中时这一点非常有用:
```
class DerivedClassName(modname.BaseClassName):
```
**实例**
```python
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
s = student('ken',10,60,3)
s.speak()
```
执行以上程序输出结果为:
```
ken 说: 我 10 岁了,我在读 3 年级
```
### 多继承
Python 同样有限的支持多继承形式。多继承的类定义形如下例:
```python
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
```
需要注意圆括号中父类的顺序若是父类中有相同的方法名而在子类使用时未指定python 从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。
```python
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
#另一个类,多重继承之前的准备
class speaker():
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s我是一个演说家我演讲的主题是 %s"%(self.name,self.topic))
#多重继承
class sample(speaker,student):
a =''
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)
test = sample("Tim",25,80,4,"Python")
test.speak() #方法名同,默认调用的是在括号中排前地父类的方法
```
执行以上程序输出结果为:
```
我叫 Tim我是一个演说家我演讲的主题是 Python
```
### 方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法,实例如下:
```python
#!/usr/bin/python3
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
```
执行以上程序输出结果为:
```
调用子类方法
```
### 类属性与方法
#### 类的私有属性
**\_\_private_attrs**:两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时**self.\_\_private_attrs**。
#### 类的方法
在类地内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数
#### 类的私有方法
**\_\_private_method**:两个下划线开头,声明该方法为私有方法,不能在类地外部调用。在类的内部调用 **slef.\_\_private_methods**
实例如下:
```python
#!/usr/bin/python3
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print (self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount) # 报错,实例不能访问私有变量
```
执行以上程序输出结果为:
```
1
2
2
Traceback (most recent call last):
File "test.py", line 16, in <module>
print (counter.__secretCount) # 报错,实例不能访问私有变量
AttributeError: 'JustCounter' object has no attribute '__secretCount'
```
#### 类的专有方法:
- \***\*init** :\*\* 构造函数,在生成对象时调用
- \***\*del** :\*\* 析构函数,释放对象时使用
- \***\*repr** :\*\* 打印,转换
- \***\*setitem** :\*\* 按照索引赋值
- \***\*getitem**:\*\* 按照索引获取值
- \***\*len**:\*\* 获得长度
- \***\*cmp**:\*\* 比较运算
- \***\*call**:\*\* 函数调用
- \***\*add**:\*\* 加运算
- \***\*sub**:\*\* 减运算
- \***\*mul**:\*\* 乘运算
- \***\*div**:\*\* 除运算
- \***\*mod**:\*\* 求余运算
- \***\*pow**:\*\* 乘方
#### 运算符重载
Python 同样支持运算符重载,我么可以对类的专有方法进行重载,实例如下:
```python
#!/usr/bin/python3
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
```
以上代码执行结果如下所示:
```
Vector(7,8)
```
## 标准库概览
### 操作系统接口
os 模块提供了不少与操作系统相关联的函数。
```python
>>> import os
>>> os.getcwd() # 返回当前的工作目录
'C:\\Python34'
>>> os.chdir('/server/accesslogs') # 修改当前的工作目录
>>> os.system('mkdir today') # 执行系统命令 mkdir
0
```
### 文件通配符
glob 模块提供了一个函数用于从目录通配符搜索中生成文件列表:
```python
>>> import glob
>>> glob.glob('*.py')
['primes.py', 'random.py', 'quote.py']
```
### 命令行参数
通用工具脚本经常调用命令行参数。这些命令行参数以链表形式存储于 sys 模块的 argv 变量。例如在命令行中执行 `python demo.py one two three` 后可以得到以下输出结果:
```python
>>> import sys
>>> print(sys.argv)
['demo.py', 'one', 'two', 'three']
```
### 错误输出重定向和程序终止
sys 还有 stdinstdout 和 stderr 属性,即使在 stdout 被重定向时,后者也可以用于显示警告和错误信息。
```python
>>> sys.stderr.write('Warning, log file not found starting a new one\n')
Warning, log file not found starting a new one
```
### 字符串正则匹配
re 模块为高级字符串处理提供了正则表达式工具。对于复杂的匹配和处理,正则表达式提供了简洁、优化的解决方案:
```python
>>> import re
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
>>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
'cat in the hat'
```
### 数学
math 模块为浮点运算提供了对底层 C 函数库的访问:
```python
>>> import math
>>> math.cos(math.pi / 4)
0.70710678118654757
>>> math.log(1024, 2)
10.0
```
# 资料
- https://github.com/vinta/awesome-python - 资源大全
- https://github.com/jobbole/awesome-python-cn - 资源大全
- https://github.com/scrapy/scrapy - python 爬虫框架
- https://github.com/faif/python-patterns - python 设计模式
- https://github.com/kennethreitz/python-guide - python 最佳实践

File diff suppressed because it is too large Load Diff

View File

@ -11,5 +11,5 @@
- [RocketMQ 安装](rocketmq-install.md) - [RocketMQ 安装](rocketmq-install.md)
- [Svn 安装](svn-ops.md) - [Svn 安装](svn-ops.md)
- [Tomcat 安装](tomcat-install.md) - [Tomcat 安装](tomcat-install.md)
- [Zookeeper 安装](zookeeper-install.md) - [Zookeeper 安装](zookeeper-ops.md)
- [Nacos 安装](nacos-install.md) - [Nacos 安装](nacos-install.md)

View File

@ -1,493 +0,0 @@
# Mysql 维护
## 安装配置
通过 rpm 包安装
centos 的 yum 源中默认是没有 mysql 的,所以我们需要先去官网下载 mysql 的 repo 源并安装。
### 安装 mysql yum 源
官方下载地址https://dev.mysql.com/downloads/repo/yum/
1下载 yum 源
```bash
$ wget https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
```
2安装 yum repo 文件并更新 yum 缓存
```bash
$ rpm -ivh mysql80-community-release-el7-1.noarch.rpm
```
执行结果:
会在 /etc/yum.repos.d/ 目录下生成两个 repo 文件
```bash
$ ls | grep mysql
mysql-community.repo
mysql-community-source.repo
```
更新 yum
```bash
$ yum clean all
$ yum makecache
```
3查看 rpm 安装状态
```bash
$ yum search mysql | grep server
mysql-community-common.i686 : MySQL database common files for server and client
mysql-community-common.x86_64 : MySQL database common files for server and
mysql-community-test.x86_64 : Test suite for the MySQL database server
: administering MySQL servers
mysql-community-server.x86_64 : A very fast and reliable SQL database server
```
通过 yum 安装 mysql 有几个重要目录:
```
# 数据库目录
/var/lib/mysql/
# 配置文件
/usr/share/mysqlmysql.server命令及配置文件
# 相关命令
/usr/binmysqladmin mysqldump等命令
# 启动脚本
/etc/rc.d/init.d/启动脚本文件mysql的目录
# 配置文件
/etc/my.cnf
```
### 安装 mysql 服务器
```bash
$ yum install mysql-community-server
```
### 启动 mysql 服务
```bash
# 启动 mysql 服务
systemctl start mysqld.service
# 查看运行状态
systemctl status mysqld.service
# 开机启动
systemctl enable mysqld
systemctl daemon-reload
```
### 初始化数据库密码
查看一下初始密码
```bash
$ grep "password" /var/log/mysqld.log
2018-09-30T03:13:41.727736Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: %:lt+srWu4k1
```
执行命令:
```bash
mysql -uroot -p<临时密码>
```
输入临时密码,进入 mysql如果要修改密码执行以下指令
```bash
ALTER user 'root'@'localhost' IDENTIFIED BY '你的密码';
```
注:密码强度默认为中等,大小写字母、数字、特殊符号,只有修改成功后才能修改配置再设置更简单的密码
### 配置远程访问
```sql
mysql> CREATE USER 'root'@'%' IDENTIFIED BY '你的密码';
mysql> GRANT ALL ON *.* TO 'root'@'%';
mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '你的密码';
mysql> FLUSH PRIVILEGES;
```
### 跳过登录认证
```
vim /etc/my.cnf
```
在 [mysqld] 下面加上 skip-grant-tables
作用是登录时跳过登录认证,换句话说就是 root 什么密码都可以登录进去。
执行 `service mysqld restart`,重启 mysql
## 部署
### 主从节点部署
假设需要配置一个主从 Mysql 服务器环境
- master 节点192.168.8.10
- slave 节点192.168.8.11
#### 配置主从同步
1主节点配置
执行 `vi /etc/my.cnf` ,添加如下配置:
```ini
[mysqld]
server-id=1
log-bin=mysql-bin
```
- `server-id` - 服务器 ID 号;
- `log-bin` - 同步的日志路径及文件名一定注意这个目录要是mysql有权限写入的
2从节点配置
执行 `vi /etc/my.cnf` ,添加如下配置:
```ini
[mysqld]
server-id=2
log-bin=mysql-bin
```
3创建用于复制操作的用户
```sql
mysql> CREATE USER 'sync'@'192.168.8.11' IDENTIFIED WITH mysql_native_password BY '密码'; -- 创建用户
mysql> GRANT REPLICATION SLAVE ON *.* TO 'sync'@'192.168.8.11'; -- 授权
mysql> FLUSH PRIVILEGES; -- 刷新授权表信息
```
4查看主节点状态
```sql
mysql> show master status;
+------------------+----------+--------------+---------------------------------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+---------------------------------------------+-------------------+
| mysql-bin.000001 | 4202 | | mysql,information_schema,performance_schema | |
+------------------+----------+--------------+---------------------------------------------+-------------------+
1 row in set (0.00 sec)
```
5在Slave节点上设置主节点参数
`MASTER_LOG_FILE``MASTER_LOG_POS` 参数要分别与 `show master status` 指令获得的 `File``Position` 属性值对应。
```sql
mysql> CHANGE MASTER TO
MASTER_HOST='192.168.199.149',
MASTER_USER='sync',
MASTER_PASSWORD='密码',
MASTER_LOG_FILE='binlog.000001',
MASTER_LOG_POS=4202;
```
6查看主从同步状态
```
mysql> show slave status\G;
```
说明:如果以下两项参数均为 YES说明配置正确。
- `Slave_IO_Running`
- `Slave_SQL_Running`
7启动 slave 进程
```
mysql> start slave;
```
#### 同步主节点已有数据到从节点
主库操作:
1停止主库的数据更新操作
```sql
mysql> flush tables with read lock;
```
2新开终端生成主数据库的备份导出数据库
```bash
$ mysqldump -uroot -p<密码> test > test.sql
```
3将备份文件传到从库
```bash
$ scp test.sql root@192.168.8.11:/root/
```
4主库解锁
```mysql
mysql> unlock tables;
```
从库操作:
1停止从库slave
```mysql
mysql> stop slave;
```
2新建数据库test
```mysql
mysql> create database test default charset utf8;
```
3导入数据
```bash
$ mysql -uroot -ptest123 cmdb<cmdb.sql
```
4查看从库已有该数据库和数据
```mysql
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| cmdb |
| mysql |
| performance_schema |
| test |
+--------------------+
```
## 运维
### 创建用户
```
CREATE USER 'username'@'host' IDENTIFIED BY 'password';
```
说明:
- username你将创建的用户名
- host指定该用户在哪个主机上可以登陆如果是本地用户可用 localhost如果想让该用户可以**从任意远程主机登陆**,可以使用通配符`%`
- password该用户的登陆密码密码可以为空如果为空则该用户可以不需要密码登陆服务器
示例:
```sql
CREATE USER 'dog'@'localhost' IDENTIFIED BY '123456';
CREATE USER 'pig'@'192.168.1.101_' IDENDIFIED BY '123456';
CREATE USER 'pig'@'%' IDENTIFIED BY '123456';
CREATE USER 'pig'@'%' IDENTIFIED BY '';
CREATE USER 'pig'@'%';
```
### 授权
命令:
```sql
GRANT privileges ON databasename.tablename TO 'username'@'host'
```
说明:
- privileges用户的操作权限如`SELECT``INSERT``UPDATE`等,如果要授予所的权限则使用`ALL`
- databasename数据库名
- tablename表名如果要授予该用户对所有数据库和表的相应操作权限则可用`*`表示,如`*.*`
示例:
```sql
GRANT SELECT, INSERT ON test.user TO 'pig'@'%';
GRANT ALL ON *.* TO 'pig'@'%';
GRANT ALL ON maindataplus.* TO 'pig'@'%';
```
注意:
用以上命令授权的用户不能给其它用户授权,如果想让该用户可以授权,用以下命令:
```sql
GRANT privileges ON databasename.tablename TO 'username'@'host' WITH GRANT OPTION;
```
### 撤销授权
命令:
```
REVOKE privilege ON databasename.tablename FROM 'username'@'host';
```
说明:
privilege, databasename, tablename同授权部分
例子:
```
REVOKE SELECT ON *.* FROM 'pig'@'%';
```
注意:
假如你在给用户`'pig'@'%'`授权的时候是这样的(或类似的):`GRANT SELECT ON test.user TO 'pig'@'%'`,则在使用`REVOKE SELECT ON *.* FROM 'pig'@'%';`命令并不能撤销该用户对 test 数据库中 user 表的`SELECT` 操作。相反,如果授权使用的是`GRANT SELECT ON *.* TO 'pig'@'%';`则`REVOKE SELECT ON test.user FROM 'pig'@'%';`命令也不能撤销该用户对 test 数据库中 user 表的`Select`权限。
具体信息可以用命令`SHOW GRANTS FOR 'pig'@'%';` 查看。
### 更改用户密码
```sql
SET PASSWORD FOR 'username'@'host' = PASSWORD('newpassword');
```
如果是当前登陆用户用:
```sql
SET PASSWORD = PASSWORD("newpassword");
```
示例:
```sql
SET PASSWORD FOR 'pig'@'%' = PASSWORD("123456");
```
### 备份与恢复
Mysql 备份数据使用 mysqldump 命令。
mysqldump 将数据库中的数据备份成一个文本文件,表的结构和表中的数据将存储在生成的文本文件中。
备份:
1备份一个数据库
语法:
```
mysqldump -u <username> -p <database> [<table1> <table2> ...] > backup.sql
```
- username 数据库用户
- dbname 数据库名称
- table1 和 table2 参数表示需要备份的表的名称,为空则整个数据库备份;
- BackupName.sql 参数表设计备份文件的名称,文件名前面可以加上一个绝对路径。通常将数据库被分成一个后缀名为 sql 的文件
2备份多个数据库
```
mysqldump -u <username> -p --databases <database1> <database2> ... > backup.sql
```
3备份所有数据库
```
mysqldump -u <username> -p -all-databases > backup.sql
```
恢复:
Mysql 恢复数据使用 mysqldump 命令。
语法:
```
mysql -u <username> -p <database> < backup.sql
```
### 卸载
1查看已安装的 mysql
```bash
$ rpm -qa | grep -i mysql
perl-DBD-MySQL-4.023-6.el7.x86_64
mysql80-community-release-el7-1.noarch
mysql-community-common-8.0.12-1.el7.x86_64
mysql-community-client-8.0.12-1.el7.x86_64
mysql-community-libs-compat-8.0.12-1.el7.x86_64
mysql-community-libs-8.0.12-1.el7.x86_64
```
2卸载 mysql
```bash
$ yum remove mysql-community-server.x86_64
```
## 问题
### JDBC 与 Mysql 因 CST 时区协商无解导致偏差了 14 或 13 小时
**现象**
数据库中存储的 Timestamp 字段值比真实值少了 13 个小时。
**原因**
- 当 JDBC 与 MySQL 开始建立连接时,会获取服务器参数。
- 当 MySQL 的 `time_zone` 值为 `SYSTEM` 时,会取 `system_time_zone` 值作为协调时区,若得到的是 `CST` 那么 Java 会误以为这是 `CST -0500` ,因此会给出错误的时区信息(国内一般是`CST +0800`,即东八区)。
> 查看时区方法:
>
> 通过 `show variables like '%time_zone%';` 命令查看 Mysql 时区配置:
>
> ```
> mysql> show variables like '%time_zone%';
> +------------------+--------+
> | Variable_name | Value |
> +------------------+--------+
> | system_time_zone | CST |
> | time_zone | SYSTEM |
> +------------------+--------+
> ```
**解决方案**
方案一
```
mysql> set global time_zone = '+08:00';
Query OK, 0 rows affected (0.00 sec)
mysql> set time_zone = '+08:00';
Query OK, 0 rows affected (0.00 sec)
```
方案二
修改 `my.cnf` 文件,在 `[mysqld]` 节下增加 `default-time-zone = '+08:00'` ,然后重启。
## 参考资料
- https://www.cnblogs.com/xiaopotian/p/8196464.html
- https://www.cnblogs.com/bigbrotherer/p/7241845.html
- https://blog.csdn.net/managementandjava/article/details/80039650
- http://www.manongjc.com/article/6996.html
- https://www.cnblogs.com/xyabk/p/8967990.html
- [MySQL 8.0主从Master-Slave配置](https://blog.csdn.net/zyhlwzy/article/details/80569422)
## :door: 传送门
| [我的 Github 博客](https://github.com/dunwu/blog) | [db-tutorial 首页](https://github.com/dunwu/db-tutorial) |

View File

@ -1,475 +0,0 @@
# Redis 运维
> **Redis** 是一个高性能的 key-value 数据库。
>
> SET 操作每秒钟 110000 次GET 操作每秒钟 81000 次。
<!-- TOC depthfrom:2 depthto:3 -->
- [安装](#安装)
- [Window 下安装](#window-下安装)
- [Linux 下安装](#linux-下安装)
- [Ubuntu 下安装](#ubuntu-下安装)
- [开机启动](#开机启动)
- [开放防火墙端口](#开放防火墙端口)
- [Redis 使用和配置](#redis-使用和配置)
- [启动](#启动)
- [常见配置](#常见配置)
- [设为守护进程](#设为守护进程)
- [远程访问](#远程访问)
- [设置密码](#设置密码)
- [配置参数表](#配置参数表)
- [Redis 集群使用和配置](#redis-集群使用和配置)
- [集群规划](#集群规划)
- [部署](#部署)
- [Redis 命令](#redis-命令)
- [压力测试](#压力测试)
- [客户端](#客户端)
- [脚本](#脚本)
- [参考资料](#参考资料)
<!-- /TOC -->
## 安装
### Window 下安装
**下载地址:**<https://github.com/MSOpenTech/redis/releases>
Redis 支持 32 位和 64 位。这个需要根据你系统平台的实际情况选择,这里我们下载 **Redis-x64-xxx.zip**压缩包到 C 盘,解压后,将文件夹重新命名为 **redis**
打开一个 **cmd** 窗口 使用 cd 命令切换目录到 **C:\redis** 运行 **redis-server.exe redis.windows.conf**
如果想方便的话,可以把 redis 的路径加到系统的环境变量里,这样就省得再输路径了,后面的那个 redis.windows.conf 可以省略,如果省略,会启用默认的。
这时候另启一个 cmd 窗口,原来的不要关闭,不然就无法访问服务端了。
切换到 redis 目录下运行 **redis-cli.exe -h 127.0.0.1 -p 6379**
### Linux 下安装
**下载地址:** http://redis.io/download下载最新文档版本。
下载、解压、编译 Redis
```
$ wget http://download.redis.io/releases/redis-5.0.4.tar.gz
$ tar xzf redis-5.0.4.tar.gz
$ cd redis-5.0.4
$ make
```
为了编译 Redis 源码,你需要 gcc-c++和 tcl。如果你的系统是 CentOS可以直接执行命令`yum install -y gcc-c++ tcl` 来安装。
进入到解压后的 `src` 目录,通过如下命令启动 Redis:
```
$ src/redis-server
```
您可以使用内置的客户端与 Redis 进行交互:
```
$ src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"
```
### Ubuntu 下安装
在 Ubuntu 系统安装 Redi 可以使用以下命令:
```
$sudo apt-get update
$sudo apt-get install redis-server
```
### 开机启动
- 开机启动配置:`echo "/usr/local/bin/redis-server /etc/redis.conf" >> /etc/rc.local`
### 开放防火墙端口
- 添加规则:`iptables -I INPUT -p tcp -m tcp --dport 6379 -j ACCEPT`
- 保存规则:`service iptables save`
- 重启 iptables`service iptables restart`
## Redis 使用和配置
### 启动
**启动 redis 服务**
```
cd /usr/local/redis/src
./redis-server
```
**启动 redis 客户端**
```
cd /usr/local/redis/src
./redis-cli
```
**查看 redis 是否启动**
```
$ redis-cli
```
以上命令将打开以下终端:
```
redis 127.0.0.1:6379>
```
127.0.0.1 是本机 IP 6379 是 redis 服务端口。现在我们输入 PING 命令。
```
redis 127.0.0.1:6379> ping
PONG
```
以上说明我们已经成功启动了 redis。
### 常见配置
> Redis 默认的配置文件是根目录下的 `redis.conf` 文件。
>
> 如果需要指定特定文件作为配置文件,需要使用命令: `./redis-server -c xxx.conf`
>
> 每次修改配置后,需要重启才能生效。
>
> Redis 官方默认配置:
>
> - 自描述文档 [redis.conf for Redis 2.8](https://raw.githubusercontent.com/antirez/redis/2.8/redis.conf)
> - 自描述文档 [redis.conf for Redis 2.6](https://raw.githubusercontent.com/antirez/redis/2.6/redis.conf).
> - 自描述文档 [redis.conf for Redis 2.4](https://raw.githubusercontent.com/antirez/redis/2.4/redis.conf).
>
> 自 Redis2.6 起就可以直接通过命令行传递 Redis 配置参数。这种方法可以用于测试。自 Redis2.6 起就可以直接通过命令行传递 Redis 配置参数。这种方法可以用于测试。
### 设为守护进程
Redis 默认以非守护进程方式启动,而通常我们会将 Redis 设为守护进程启动方式,配置:`daemonize yes`
#### 远程访问
Redis 默认绑定 127.0.0.1,这样就只能本机才能访问,若要 Redis 允许远程访问,需要配置:`bind 0.0.0.0`
#### 设置密码
Redis 默认访问不需要密码,如果需要设置密码,需要如下配置:
- `protected-mode yes`
- `requirepass <密码>`
#### 配置参数表
| 配置项 | 说明 |
| :-- | :-- |
| `daemonize no` | Redis 默认不是以守护进程的方式运行,可以通过该配置项修改,使用 yes 启用守护进程Windows 不支持守护线程的配置为 no |
| `pidfile /var/run/redis.pid` | 当 Redis 以守护进程方式运行时Redis 默认会把 pid 写入 /var/run/redis.pid 文件,可以通过 pidfile 指定 |
| `port 6379` | 指定 Redis 监听端口,默认端口为 6379作者在自己的一篇博文中解释了为什么选用 6379 作为默认端口,因为 6379 在手机按键上 MERZ 对应的号码,而 MERZ 取自意大利歌女 Alessia Merz 的名字 |
| `bind 127.0.0.1` | 绑定的主机地址 |
| `timeout 300` | 当客户端闲置多长时间后关闭连接,如果指定为 0表示关闭该功能 |
| `loglevel notice` | 指定日志记录级别Redis 总共支持四个级别debug、verbose、notice、warning默认为 notice |
| `logfile stdout` | 日志记录方式,默认为标准输出,如果配置 Redis 为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给 /dev/null |
| `databases 16` | 设置数据库的数量,默认数据库为 0可以使用 SELECT 命令在连接上指定数据库 id |
| `save <seconds> <changes>` Redis 默认配置文件中提供了三个条件:**save 900 1**、**save 300 10**、**save 60 10000** 分别表示 900 秒15 分钟)内有 1 个更改300 秒5 分钟)内有 10 个更改以及 60 秒内有 10000 个更改。 | 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合 |
| `rdbcompression yes` | 指定存储至本地数据库时是否压缩数据,默认为 yesRedis 采用 LZF 压缩,如果为了节省 CPU 时间,可以关闭该选项,但会导致数据库文件变的巨大 |
| `dbfilename dump.rdb` | 指定本地数据库文件名,默认值为 dump.rdb |
| `dir ./` | 指定本地数据库存放目录 |
| `slaveof <masterip> <masterport>` | 设置当本机为 slav 服务时,设置 master 服务的 IP 地址及端口,在 Redis 启动时,它会自动从 master 进行数据同步 |
| `masterauth <master-password>` | 当 master 服务设置了密码保护时slav 服务连接 master 的密码 |
| `requirepass foobared` | 设置 Redis 连接密码,如果配置了连接密码,客户端在连接 Redis 时需要通过 AUTH <password> 命令提供密码,默认关闭 |
| `maxclients 128` | 设置同一时间最大客户端连接数默认无限制Redis 可以同时打开的客户端连接数为 Redis 进程可以打开的最大文件描述符数,如果设置 maxclients 0表示不作限制。当客户端连接数到达限制时Redis 会关闭新的连接并向客户端返回 max number of clients reached 错误信息 |
| `maxmemory <bytes>` | 指定 Redis 最大内存限制Redis 在启动时会把数据加载到内存中达到最大内存后Redis 会先尝试清除已到期或即将到期的 Key当此方法处理 后仍然到达最大内存设置将无法再进行写入操作但仍然可以进行读取操作。Redis 新的 vm 机制,会把 Key 存放内存Value 会存放在 swap 区 |
| `appendonly no` | 指定是否在每次更新操作后进行日志记录Redis 在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis 本身同步数据文件是按上面 save 条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为 no |
| `appendfilename appendonly.aof` | 指定更新日志文件名,默认为 appendonly.aof |
| `appendfsync everysec` | 指定更新日志条件,共有 3 个可选值:**no**:表示等操作系统进行数据缓存同步到磁盘(快)**always**:表示每次更新操作后手动调用 fsync() 将数据写到磁盘(慢,安全)**everysec**:表示每秒同步一次(折中,默认值) |
| `vm-enabled no` | 指定是否启用虚拟内存机制,默认值为 no简单的介绍一下VM 机制将数据分页存放,由 Redis 将访问量较少的页即冷数据 swap 到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析 Redis 的 VM 机制) |
| `vm-swap-file /tmp/redis.swap` | 虚拟内存文件路径,默认值为 /tmp/redis.swap不可多个 Redis 实例共享 |
| `vm-max-memory 0` | 将所有大于 vm-max-memory 的数据存入虚拟内存,无论 vm-max-memory 设置多小,所有索引数据都是内存存储的(Redis 的索引数据 就是 keys),也就是说,当 vm-max-memory 设置为 0 的时候,其实是所有 value 都存在于磁盘。默认值为 0 |
| `vm-page-size 32` | Redis swap 文件分成了很多的 page一个对象可以保存在多个 page 上面,但一个 page 上不能被多个对象共享vm-page-size 是要根据存储的 数据大小来设定的作者建议如果存储很多小对象page 大小最好设置为 32 或者 64bytes如果存储很大大对象则可以使用更大的 page如果不确定就使用默认值 |
| `vm-pages 134217728` | 设置 swap 文件中的 page 数量,由于页表(一种表示页面空闲或使用的 bitmap是在放在内存中的在磁盘上每 8 个 pages 将消耗 1byte 的内存。 |
| `vm-max-threads 4` | 设置访问 swap 文件的线程数,最好不要超过机器的核数,如果设置为 0,那么所有对 swap 文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为 4 |
| `glueoutputbuf yes` | 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启 |
| `hash-max-zipmap-entries 64 hash-max-zipmap-value 512` | 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法 |
| `activerehashing yes` | 指定是否激活重置哈希,默认为开启(后面在介绍 Redis 的哈希算法时具体介绍) |
| `include /path/to/local.conf` | 指定包含其它的配置文件,可以在同一主机上多个 Redis 实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件 |
## Redis 集群使用和配置
Redis 3.0 后支持集群模式。
### 集群规划
`Redis` 集群一般由 **多个节点** 组成,节点数量至少为 `6` 个,才能保证组成 **完整高可用** 的集群。
<div align="center"><img src="https://user-gold-cdn.xitu.io/2019/10/10/16db5250b0d1c392?w=1467&h=803&f=png&s=43428"/></div>
理想情况当然是所有节点各自在不同的机器上,首先于资源,本人在部署 Redis 集群时,只得到 3 台服务器。所以,我计划每台服务器部署 2 个 Redis 节点。
### 部署
Redis 集群节点的安装与单节点服务相同,差异仅在于部署方式。
假设三台服务器地址如下:
- 服务 A127.0.0.1
- 服务 B127.0.0.2
- 服务 C127.0.0.3
分配如下:
| 127.0.0.1 | 127.0.0.2 | 127.0.0.3 |
| -------------- | -------------- | -------------- |
| 127.0.0.1:6381 | 127.0.0.2:6383 | 127.0.0.3:6385 |
| 127.0.0.1:6382 | 127.0.0.2:6384 | 127.0.0.3:6386 |
#### 1创建节点目录
我个人偏好将软件放在 `/opt` 目录下在我的机器中Redis 都安装在 `/usr/local/redis` 目录下。所以,下面的命令和配置都假设 Redis 安装目录为 `/usr/local/redis`
确保机器上已经安装了 Redis 后,执行以下命令,创建 Redis 集群节点实例目录:
- 127.0.0.1
```bash
sudo mkdir -p /usr/local/redis/cluster/6381
sudo mkdir -p /usr/local/redis/cluster/6382
```
- 127.0.0.2
```bash
sudo mkdir -p /usr/local/redis/cluster/6383
sudo mkdir -p /usr/local/redis/cluster/6384
```
- 127.0.0.3
```bash
sudo mkdir -p /usr/local/redis/cluster/6385
sudo mkdir -p /usr/local/redis/cluster/6386
```
#### 2集群节点实例配置
每个实例目录下,新建 `redis.conf` 配置文件。
实例配置模板以 6381 节点为例(其他节点,完全替换配置中的端口号 6381 即可),如下:
```
# 端口号
port 6381
# 绑定的主机端口0.0.0.0 表示允许远程访问)
bind 0.0.0.0
# 以守护进程方式启动
daemonize yes
# 开启集群模式
cluster-enabled yes
# 集群的配置,配置文件首次启动自动生成
cluster-config-file /usr/local/redis/cluster/6381/6381.conf
# 请求超时时间,设置 10 秒
cluster-node-timeout 10000
# 开启 AOF 持久化
appendonly yes
# 数据存放目录
dir /usr/local/redis/cluster/6381
# 进程文件
pidfile /var/run/redis/redis-6381.pid
# 日志文件
logfile /usr/local/redis/cluster/6381/6381.log
```
#### 3启动 Redis 节点
Redis 的 utils/create-cluster 目录下自带了一个名为 create-cluster 的脚本工具,可以利用它来新建、启动、停止、重启 Redis 节点。
脚本中有几个关键参数:
- `PORT`=30000 - 初始端口号
- `TIMEOUT`=2000 - 超时时间
- `NODES`=6 - 节点数
- `REPLICAS`=1 - 备份数
脚本中的每个命令项会根据初始端口号,以及设置的节点数,遍历的去执行操作。
由于前面的规划中,节点端口是从 6381 ~ 6386所以需要将 PORT 变量设为 6380。
脚本中启动每个 Redis 节点是通过指定命令行参数来配置属性。所以,我们需要改一下:
```bash
if [ "$1" == "start" ]
then
while [ $((PORT < ENDPORT)) != "0" ]; do
PORT=$((PORT+1))
echo "Starting $PORT"
/usr/local/redis/src/redis-server /usr/local/redis/cluster/${PORT}/redis.conf
done
exit 0
fi
```
好了,在每台服务器上,都执行 `./create-cluster start` 来启动节点。
然后,通过 ps 命令来确认 Redis 进程是否已经工作:
```
$ ps -ef | grep redis
root 12036 1 12 16:26 ? 00:08:28 /usr/local/redis/src/redis-server 0.0.0.0:6381 [cluster]
root 12038 1 0 16:26 ? 00:00:03 /usr/local/redis/src/redis-server 0.0.0.0:6382 [cluster]
```
#### 4启动集群
通过 `redis-cli --cluster create` 命令可以自动配置集群,如下:
```bash
$ /usr/local/redis/src/redis-cli --cluster create 127.0.0.1:6381 127.0.0.1:6382 127.0.0.2:6383 127.0.0.2:6384 127.0.0.3:6385 127.0.0.3:6386 --cluster-replicas 1
```
如果启动成功,可以看到如下信息:
```
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.2:6384 to 127.0.0.1:6381
Adding replica 127.0.0.3:6386 to 127.0.0.2:6383
Adding replica 127.0.0.1:6382 to 127.0.0.3:6385
M: 75527b790e46530ea271a5b78f9e0fd9030f68e0 127.0.0.1:6381
slots:[0-5460] (5461 slots) master
S: 031dd0fd5ad90fa26fcf45d49ad906d063611a6d 127.0.0.1:6382
replicates 53012ebdd25005840da9ecbe07d937296a264206
M: 0cfbceec272b6ff70e1dfb5c5346a5cb2c20c884 127.0.0.2:6383
slots:[5461-10922] (5462 slots) master
S: 016ae9624202891cc6f2b480ff0634de478197fb 127.0.0.2:6384
replicates 75527b790e46530ea271a5b78f9e0fd9030f68e0
M: 53012ebdd25005840da9ecbe07d937296a264206 127.0.0.3:6385
slots:[10923-16383] (5461 slots) master
S: b6d70f2ed78922b1dcb7967ebe1d05ad9157fca8 127.0.0.3:6386
replicates 0cfbceec272b6ff70e1dfb5c5346a5cb2c20c884
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
....
>>> Performing Cluster Check (using node 127.0.0.1:6381)
M: 75527b790e46530ea271a5b78f9e0fd9030f68e0 127.0.0.1:6381
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 0cfbceec272b6ff70e1dfb5c5346a5cb2c20c884 127.0.0.2:6383
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 016ae9624202891cc6f2b480ff0634de478197fb 127.0.0.2:6384
slots: (0 slots) slave
replicates 75527b790e46530ea271a5b78f9e0fd9030f68e0
M: 53012ebdd25005840da9ecbe07d937296a264206 127.0.0.3:6385
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 031dd0fd5ad90fa26fcf45d49ad906d063611a6d 127.0.0.1:6382
slots: (0 slots) slave
replicates 53012ebdd25005840da9ecbe07d937296a264206
S: b6d70f2ed78922b1dcb7967ebe1d05ad9157fca8 127.0.0.3:6386
slots: (0 slots) slave
replicates 0cfbceec272b6ff70e1dfb5c5346a5cb2c20c884
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
```
#### 5日常维护操作
- 关闭集群 - `./create-cluster stop`
- 检查集群是否健康(指定任意节点即可):`./redis-cli --cluster check <ip:port>`
- 尝试修复集群节点:`./redis-cli --cluster fix <ip:port>`
## Redis 命令
> 命令详细用法,请参考 [**Redis 命令官方文档**](https://redis.io/commands)
>
> 搬迁两张 cheat sheet 图原址https://www.cheatography.com/tasjaevan/cheat-sheets/redis/
<div align="center"><img src="https://user-gold-cdn.xitu.io/2019/10/10/16db5250b0b8ea57?w=2230&h=2914&f=png&s=246433"/></div>
<div align="center"><img src="https://user-gold-cdn.xitu.io/2019/10/10/16db5250b0e9ba3c?w=2229&h=2890&f=png&s=192997"/></div>
## 压力测试
> 参考官方文档:[How fast is Redis?](https://redis.io/topics/benchmarks)
Redis 自带了一个性能测试工具:`redis-benchmark`
**1基本测试**
```
$ redis-benchmark -q -n 100000
```
- `-q` 表示静默quiet执行
- `-n 100000` 请求 10 万次
**2测试指定读写指令**
```
$ redis-benchmark -t set,lpush -n 100000 -q
SET: 74239.05 requests per second
LPUSH: 79239.30 requests per second
```
**3测试 pipeline 模式下指定读写指令**
```
redis-benchmark -n 1000000 -t set,get -P 16 -q
SET: 403063.28 requests per second
GET: 508388.41 requests per second
```
## 客户端
推荐使用 [**RedisDesktopManager**](https://github.com/uglide/RedisDesktopManager)
## 脚本
> CentOS7 环境安装脚本:[软件运维配置脚本集合](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/soft)
**安装说明**
- 采用编译方式安装 Redis, 并将其注册为 systemd 服务
- 安装路径为:`/usr/local/redis`
- 默认下载安装 `5.0.4` 版本,端口号为:`6379`,密码为空
**使用方法**
- 默认安装 - 执行以下任意命令即可:
```sh
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/redis-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/redis-install.sh | bash
```
- 自定义安装 - 下载脚本到本地,并按照以下格式执行:
```sh
sh redis-install.sh [version] [port] [password]
```
参数说明:
- `version` - redis 版本号
- `port` - redis 服务端口号
- `password` - 访问密码
## 参考资料
- [Redis 官方文档](https://redis.io)
- [深入剖析 Redis 系列(三) - Redis 集群模式搭建与原理详解](https://juejin.im/post/5b8fc5536fb9a05d2d01fb11)

View File

@ -1,96 +0,0 @@
# ZooKeeper 安装部署
> 环境要求JDK6+
<!-- TOC depthFrom:2 depthTo:3 -->
- [下载解压 ZooKeeper](#下载解压-zookeeper)
- [创建配置文件](#创建配置文件)
- [启动 ZooKeeper 服务器](#启动-zookeeper-服务器)
- [启动 CLI](#启动-cli)
- [停止 ZooKeeper 服务器](#停止-zookeeper-服务器)
<!-- /TOC -->
在安装 ZooKeeper 之前,请确保你的系统是在以下任一操作系统上运行:
- **任意 Linux OS** - 支持开发和部署。适合演示应用程序。
- **Windows OS** - 仅支持开发。
- **Mac OS** - 仅支持开发。
安装步骤如下:
## 下载解压 ZooKeeper
进入官方下载地址http://zookeeper.apache.org/releases.html#download ,选择合适版本。
解压到本地:
```
$ tar -zxf zookeeper-3.4.6.tar.gz
$ cd zookeeper-3.4.6
```
## 创建配置文件
你必须创建 `conf/zoo.cfg` 文件,否则启动时会提示你没有此文件。
初次尝试,不妨直接使用 Kafka 提供的模板配置文件 `conf/zoo_sample.cfg`
```
$ cp conf/zoo_sample.cfg conf/zoo.cfg
```
## 启动 ZooKeeper 服务器
执行以下命令
```
$ bin/zkServer.sh start
```
执行此命令后,你将收到以下响应
```
$ JMX enabled by default
$ Using config: /Users/../zookeeper-3.4.6/bin/../conf/zoo.cfg
$ Starting zookeeper ... STARTED
```
## 启动 CLI
键入以下命令
```
$ bin/zkCli.sh
```
键入上述命令后,将连接到 ZooKeeper 服务器,你应该得到以下响应。
```
Connecting to localhost:2181
................
................
................
Welcome to ZooKeeper!
................
................
WATCHER::
WatchedEvent state:SyncConnected type: None path:null
[zk: localhost:2181(CONNECTED) 0]
```
## 停止 ZooKeeper 服务器
连接服务器并执行所有操作后,可以使用以下命令停止 zookeeper 服务器。
```
$ bin/zkServer.sh stop
```
> 本节安装内容参考:[Zookeeper 安装](https://www.w3cschool.cn/zookeeper/zookeeper_installation.html)
## 更多内容
- **引申**
- [操作系统、运维部署总结系列](https://github.com/dunwu/OS)

View File

@ -1,324 +0,0 @@
---
title: Mac
date: 2019-03-06
---
# Mac
## 基本操作
### 软件管理
dmg 格式:双击安装包,然后拖到 applications 文件夹下即可。
### 浏览器
#### 更改默认搜索引擎
选择「偏好设置--\>搜索--\>搜索引擎--\>Google」。
#### 导入 chrome 浏览器的书签
选择「文件-->导入自--> Google Chrome」然后选择要导入的项目。
#### 快捷键
Command + R 刷新
#### 上方显示书签栏/收藏栏
选择「显示--> 显示个人收藏栏」。
#### 关闭软件的右上角通知
在 Mac 系统中有对通知的设置,打开系统偏好设置 — 通知 找到 QQ然后将 QQ 提示样式设置成无即可。
#### 复制文件/文件夹路径
- OS X 10.11 系统选中文件夹「cmd +Option +c」 复制文件夹路径cmd+v 粘贴。
之前的系统,利用 Administrator 创建一个到右键菜单,然后到设置里面设置快捷键。具体操作请百度。
#### 打开来自身份不明的开发者的应用程序
在应用程序文件夹,按住 control 键的同时打开应用程序。
#### 复制文件路径
- 选择文件/文件夹按 Command+C 复制,在终端中 Command+V 粘贴即可。
- 如果只是想在 Finder 中看到文件的路径, 并方便切换层级, Finder 内置了「显示路径栏」的功能, 并配置了快捷键(Option+Cmd+P). 如下图所示:
20161124-184148.png
参考链接:
- [https://www.zhihu.com/question/22883229]
### 隐藏和取消隐藏 Mac App Store 中的已购项目
### Mac 同时登陆两个 QQ
在已经打开的 QQ 中按住「command + N」即可。
## 系统便好设置
### 语音播报
打开「系统便好设置-->辅助功能-->语音」,即可设置不同国家的语言。
勾选上图中的红框部分,可以设置全局快捷键。这样的话,在任何一个软件当中,按下「 option+esc」时就会朗读选中的文本。
### 调整字体大小
Mac 调整字体大小:「系统偏好设置 -> 显示器 -> 缩放」。如下图:
### 如何分别设置 Mac 的鼠标和触控板的滚动方向
很多人习惯鼠标使用相反的滚动方向,而触控板类似 iPad 那样的自然滚动,问如何设置,当时我的回答是不知道,因为目前 OS X 的系统设置里,鼠标和触控板的设置是统一
的。今天发现了一个免费的软件 Scroll Reverser可以实现鼠标和触控板的分别设置。下载地址<https://pilotmoon.com/scrollreverser/>
启动后程序显示在顶部菜单栏,设置简单明了,有需要的用户体验一下吧。
### Touch Bar 自定义
打开「系统偏好设置-键盘」,下面有个自定义控制条。
### 色温调节:夜间模式
iOS9.3 的最明显变化,莫过于苹果在发布会上特意提到的 Night Shift 夜间护眼模式。
### iCloud 邮箱
如果您用于设置 iCloud 的 Apple ID 不以“@icloud.com”、“@me.com”或“@mac.com”结尾您必须先设置一个“@icloud.com”电子邮件地址然后才能使用 iCloud“邮件”。
如果您拥有以“@mac.com”或“@me.com”结尾的电子邮件地址则您已经拥有了名称相同但以“@icloud.com”结尾的等效地址。如果您使用的电子邮件别名以“@mac.com”或“@me.com”结尾您也将拥有以“@icloud.com”结尾的等效地址。
**操作如下:**
- 在 iOS 设备上,前往“设置”>“iCloud”开启“邮件”然后按照屏幕上的说明操作。
- 在 Mac 上,选取 Apple 菜单 >“系统偏好设置”点按“iCloud”再选择“邮件”然后按照屏幕上的说明操作。
PS创建 iCloud 电子邮件地址后,您无法对其进行更改。
设置 @icloud.com 电子邮件地址后即可用其登录 iCloud。您也可以用创建 iCloud 帐户时所用的 Apple ID 登录。
您可以从以下任意地址发送 iCloud 电子邮件:
您的 iCloud 电子邮件地址(您的帐号名称@icloud.com
别名
参考链接:
**直接注册以@icloud.com 结尾的 Apple ID**
参考链接:
## PodCast
PodCast 中文翻译为播客,是一种特殊的音频 or 视频节目。PodCast 这个单词是由 iPod+Broadcast 这两个单词组成的。
PodCast 可以在 iTunes 中收听。
## others
### 词典
系统有一个自带应用「词典」,可以进行单词的查询。
### 如何解决 MAC 软件dmgakpapp出现程序已损坏的提示
「xxx.app 已损坏,打不开.你应该将它移到废纸篓」,并非你安装的软件已损坏,而是 Mac 系统的安全设置问题,因为这些应用都是破解或者汉化的,那么解决方法就是临时改变 Mac 系统安全设置。
出现这个问题的解决方法:修改系统配置:系统偏好设置... -> 安全性与隐私。修改为任何来源。
如果没有这个选项的话macOS Sierra 10.12,打开终端,执行:
```bash
sudo spctl --master-disable
```
即可。
参考链接:
- [Max OS-[xxx.app 已损坏,打不开.你应该将它移到废纸篓]](http://www.jianshu.com/p/379b49b88df9)
- [如何解决 MAC 软件dmgakpapp出现程序已损坏的提示](http://www.yunrui.co/25693.html)
备注:这个链接里的各种资源都很不错啊。
#### 终端
#### 在 Finder 的当前目录打开终端
在 Finder 打开 terminal 终端这个功能其实是有的,但是系统默认没有打开。我们可以通过如下方法将其打开:
进入系统偏好设置->键盘->快捷键->服务。
在右边新建位于文件夹位置的终端窗口上打勾。
如此设置后,在 Finder 中右击某文件,在出现的菜单中找到服务,然后点击新建位于文件夹位置的终端窗口即可!
## Mac 常用快捷键
### Finder
| 快捷键 | 作用 | 备注 |
| :------------------ | :------------------- | :----------------- |
| Shift + Command + G | 前往指定路径的文件夹 | 包括隐藏文件夹 |
| Shift + Command + . | 显示隐藏文件、文件夹 | 再按一次,恢复隐藏 |
| Command + ↑ | 返回上一层 | |
| Command + ↓ | 进入当前文件夹 | |
### 编辑
**删除文字**
| 快捷键 | 作用 | 备注 |
| :----------------------- | :--------------------- | :---------------------------- |
| delete | 删除光标的前一个字符 | 相当于 Windows 键盘上的退格键 |
| fn + delete | 删除光标的后一个字符 | |
| option + delete | 删除光标之前的一个单词 | 英文有效 |
| **command + delete** | 删除光标之前的整行内容 | 【荐】 |
| command + delete | 在 finder 中删掉该文件 | |
| shift + command + delete | 清空回收站 | |
**剪切文件**
首先选中文件,按 Command+C 复制文件然后按「Command Option V」剪切文件。
备注Command+X 只能剪切文字文本,不要混淆了。
## Mac 用户必须知道的 15 组快捷键
> 参考链接:[《轻松玩 Mac》第 6 期Mac 用户必须知道的 15 组快捷键](http://v.youku.com/v_show/id_XNDE4MzM0NDgw.html)
### 「space」键快速预览
选中文件后, 不需要启动任何应用程序使用「space」空格键可进行快速预览再次按下「space」空格键取消预览。
可以预览 mp3、视频、pdf 等文件。
我们还可以**选中多张图片** 然后按「space」键就可以同时对比预览多张图片。这一点很赞。
### 改名
选中文件/文件夹后,按 enter 键,就可以改名了。
### 「command + I」键查看文件属性
- 选中文件后按「command + I」键可以查看文件的各种属性。
- 选中**文件夹**后按「command + I」键可以查看文件夹的大小。【荐】
### 切换输入法
「control + space」
### 打开 spotlight 搜索框
spotlight 是系统自带的软件,搜索功能不是很强大。我们一般都会用第三方的 Alfred 软件。
### 编辑相关
Cmd+C、Cmd+V、Cmd+X、Cmd+A、Cmd+Z。
### 翻页和光标
- 「control + ↑」:将光标定位到文章的最开头(翻页到文档的最上方)
- 「control + ↓」:将光标定位到文章的最末尾(翻页到文档的最下方)
- 「control + ←」:将光标定位到当前行的最左侧
- 「control + →」:将光标定位到当前行的最右侧
### 「command + shift + Y」将文字快速保存到便笺
选中你想要的内容(例如文字、链接等),然后按下 command + shift + Y」那么你选中的内容就会快速保存到系统自带的「便笺」软件中。
如果你想临时性的保存一段内容,这个操作很实用。
### 程序相关
- 「command + Q」快速退出程序
- 「command + tab」切换程序
- 「command + H」隐藏当前应用程序。这是一个有趣的快捷键。
- 「command + ,」:打开当前应用程序的「偏好设置」。
### 窗口相关
- 「command + N」新建一个当前应用程序的窗口
- 「command + `」:在当前应用程序的不同窗口之间切换【很实用】
我们知道「command + tab」是在不同的软件之间切换。但你不知道的是「command + `」是在同一个软件的不同窗口之间切换。
- 「command + M」将当前窗口最小化
- 「command + W」关闭当前窗口
### 浏览器相关
- 「command + T」浏览器中新建一个标签
- 「command + W」关闭当前标签
* 「command + R」强制刷新。
- 「command + L」定位到地址栏。【重要】
### 截图相关
- 「command + shift + 3」截全屏对整个屏幕截图
### 声音相关
选中文字后按住「ctrl + esc」键会将文字进行朗读。我发现在触控条版的 mac 上,并没有生效)
### Dock 栏相关
- 「option + command + D」隐藏 dock 栏
### 强制推出
> 强制退出的快捷键非常重要
- 「option + command + esc」打开强制退出的窗口
### option 相关
> 强烈推荐
- 「option + command + H」隐藏除当前应用程序之外的其他应用程序
- 在文本中按住「option」键配合鼠标的选中可以进行块状文字选取。
- 「option + command + W」快速关闭当前应用程序的所有窗口。【很实用】
比如说,你一次性打开了很多文件的详情,然后就可以通过此快捷键,将这些窗口一次性关闭。
- 「option + command + I」查看多个文件的总的属性。
* 打开 launchpad按住「option」键可以快速卸载应用程序。
* 在 dock 栏右键点击软件图标同时按住「option」键就可以**强制退出**该软件。【重要】
- 在 Safari 浏览器中按住「option + command + Q」退出 Safari。等下次进入 Safari 的时候,上次退出时的网址会自动被打开。【实用】
### 推荐一个软件CheatSheet
打开 CheatSheet 后,长按 command 键,会弹出当前应用程序的所有快捷键。我们还可以对这些快捷键进行保存。
## 📚 学习资源
- [Awesome Mac](https://github.com/jaywcjlove/awesome-mac)
- [awesome-macos-command-line](https://github.com/herrbischoff/awesome-macos-command-line)
## :door: 传送门
| [回首頁](https://github.com/dunwu/blog) |

53
docs/sidebar.md 100644
View File

@ -0,0 +1,53 @@
## 文章
- [**Linux 命令**](linux/cli/README.md)
- [查看 Linux 命令帮助信息](linux/cli/查看Linux命令帮助信息.md)
- [Linux 文件目录管理](linux/cli/Linux文件目录管理.md)
- [Linux 文件内容查看命令](linux/cli/Linux文件内容查看编辑.md)
- [Linux 文件压缩和解压](linux/cli/Linux文件压缩和解压.md)
- [Linux 用户管理](linux/cli/Linux用户管理.md)
- [Linux 系统管理](linux/cli/Linux系统管理.md)
- [Linux 网络管理](linux/cli/Linux网络管理.md)
- [Linux 硬件管理](linux/cli/Linux硬件管理.md)
- [Linux 软件管理](linux/cli/Linux硬件管理.md)
- [**Linux 系统运维**](linux/ops/README.md)
- [linux 典型运维应用](linux/ops/linux典型运维应用.md)
- [samba 使用详解](linux/ops/samba使用详解.md)
- [Systemd 教程](linux/ops/systemd.md)
- [Vim 应用指南](linux/ops/vim.md)
- [Zsh 应用指南](linux/ops/zsh.md)
- [**软件运维**](linux/soft/README.md)
- 开发环境
- [JDK 安装](linux/soft/jdk-install.md)
- [Maven 安装](linux/soft/maven-install.md)
- [Nodejs 安装](linux/soft/nodejs-install.md)
- 开发工具
- [Nexus 运维](linux/soft/nexus-ops.md)
- [Gitlab 运维](linux/soft/kafka-install.md)
- [Jenkins 运维](linux/soft/jenkins.md)
- [Svn 运维](linux/soft/svn-ops.md)
- [YApi 运维](linux/soft/yapi-ops.md)
- 中间件服务
- [Elastic 运维](linux/soft/elastic)
- [Kafka 运维](linux/soft/kafka-install.md)
- [RocketMQ 运维](linux/soft/rocketmq-install.md)
- [Nacos 运维](linux/soft/nacos-install.md)
- [Zookeeper 运维](https://github.com/dunwu/javaweb/blob/master/docs/technology/monitor/zookeeper-ops.md)
- 服务器
- [Nginx 教程 📚](https://github.com/dunwu/nginx-tutorial)
- [Tomcat 运维](linux/soft/tomcat-install.md)
- [数据库 📚](https://github.com/dunwu/db-tutorial)
- [Mysql 运维](https://github.com/dunwu/db-tutorial/blob/master/docs/sql/mysql/mysql-ops.md)
- [Redis 运维](https://github.com/dunwu/db-tutorial/blob/master/docs/nosql/redis/redis-ops.md)
- **扩展**
- [Docker 教程](docker)
- [Docker 应用指南](docker/docker.md)
- [Docker Cheat Sheet](docker/docker-cheat-sheet.md)
- [一篇文章让你彻底掌握 Python](https://github.com/dunwu/blog/blob/master/source/_posts/coding/python.md)
- [一篇文章让你彻底掌握 Shell](https://github.com/dunwu/blog/blob/master/source/_posts/coding/shell.md)
- [Git 从入门到精通](https://github.com/dunwu/blog/blob/master/source/_posts/tools/git.md)
## 脚本
- [**Shell 脚本大全**](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/sys)
- [**CentOS 常规操作运维脚本集合**](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/sys)

View File

@ -1,130 +0,0 @@
---
title: 程序员玩转 Windows
categories: ['os']
tags: ['os', 'windows']
date: 2019-03-22 15:53
---
# 程序员玩转 Windows
<!-- TOC depthFrom:2 depthTo:3 -->
- [软件](#软件)
- [视频音频](#视频音频)
- [压缩](#压缩)
- [文件管理](#文件管理)
- [开发](#开发)
- [编辑器](#编辑器)
- [文档](#文档)
- [效率提升](#效率提升)
- [办公](#办公)
- [个性化](#个性化)
- [参考资料](#参考资料)
<!-- /TOC -->
## 软件
> 扩展阅读:
>
> - [Awesome Windows](https://github.com/Awesome-Windows/Awesome/blob/master/README-cn.md)
> - [best-windows-apps](https://github.com/stackia/best-windows-apps)
### 视频音频
- [Musicbee](http://getmusicbee.com/) - 类似 iTunes但比 iTunes 更好用。
- [ScreenToGif](http://www.screentogif.com/) - 它允许你录制屏幕的一部分区域并保存为 gif 或视频。
- [PotPlayer](http://potplayer.daum.net/) - 多媒体播放器,具有广泛的编解码器集合,它还为用户提供大量配置选项。
- [射手影音播放器](http://www.splayer.org/) - 来自射手网,小巧开源,首创自动匹配字幕功能。
### 压缩
- [7-Zip](http://www.7-zip.org/) - 用于处理压缩包的开源 Windows 实用程序。完美支持 7zZIPGZIPBZIP2 和 TAR 的全部特性,其他格式也可解压缩。
- [WinRAR](http://www.rarlab.com/) - 强大的归档管理器。 它可以备份您的数据并减小电子邮件附件的大小,解压缩 RARZIP 和其他文件。
### 文件管理
- [Clover](http://en.ejie.me/) - 为资源管理器加上多标签功能。
- [Total Commander](http://www.ghisler.com/) - 老牌、功能异常强大的文件管理增强软件。
- [Q-Dir](http://www.softwareok.com/?seite=Freeware/Q-Dir) - 轻量级的文件管理器,各种布局视图切换灵活,默认四个小窗口组成一个大窗口,操作快捷。软件虽小,粉丝忠诚。
- [WoX](https://github.com/Wox-launcher/Wox) - 新一代文件定位工具,堪称 Windows 上的 Alfred。
- [Everything](http://www.voidtools.com/) - 最快的文件/文件夹搜索工具, 通过名称搜索。
- [Listary](http://www.listary.com/) - 非常优秀的 Windows 文件浏览和搜索增强工具。
- Beyond Compare - 好用又万能的文件对比工具。
- [CCleaner](https://www.piriform.com/ccleaner/download) - 如果你有系统洁癖,那一定要选择一款干净、良心、老牌的清洁软件。
- [chocolatey](https://chocolatey.org/) - 包管理器
- [Ninite](https://ninite.com/) - 最简单,最快速的更新或安装软件的方式。
- [Recuva](http://www.piriform.com/RECUVA) - 来自 piriform 梨子公司产品,免费的数据恢复工具。
- [Launchy](http://www.launchy.net/):自由的跨平台工具,帮助你忘记开始菜单、桌面图标甚至文件管理器。
### 开发
- [Fiddler](http://www.telerik.com/fiddler) - web 调试代理工具。
- [Postman](https://www.getpostman.com/postman) - 适合 API 开发的完整工具链,最常用的 REST 客户端。
- [SourceTree](https://www.sourcetreeapp.com/) - 一个免费的 Git & Mercurial 客户端。
- [TortoiseSVN](https://tortoisesvn.net/) - Subversion(SVN)的图形客户端
- [Wireshark](https://www.wireshark.org/) - 一个网络协议分析工具。
- Switchhosts
- [Cmder](https://github.com/cmderdev/cmder) - 控制台模拟器包。扩展阅读:[Win 下必备神器之 Cmder](https://www.jeffjade.com/2016/01/13/2016-01-13-windows-software-cmder/)
- [Babun](http://babun.github.io/) - 基于 Cygwin用于替代 Windows shell。
### 编辑器
- [JetBrain IDE 系列](http://www.jetbrains.com/) - 真香!
- [Visual Studio Code](https://code.visualstudio.com/) - 用于构建和调试现代 Web 和云应用程序。
- [Eclipse](https://eclipse.org/downloads/) - 一款功能强大的 IDE。
- [Visual Studio](https://www.visualstudio.com/vs/) - 微软官方的 IDE通过插件可支持大量编程语言。
- [NetBeans IDE](https://netbeans.org/) - 免费开源的 IDE。
- [Typora](https://www.typora.io/) - 个人觉得最好用的 Markdown 编辑器。
- [Cmd Markdown](https://www.zybuluo.com/cmd/) - 跨平台优秀 Markdown 编辑器,本文即用其所写。
- [Notepad++](https://notepad-plus-plus.org/) - 一款支持多种编程语言的源码编辑器。
- [Notepad2](http://www.flos-freeware.ch/notepad2.html) - 用于替代默认文本编辑器的轻量快速的编辑器,拥有众多有用的功能。
- [Sublime Text 3](http://www.sublimetext.com/3) - 高级文本编辑器。
- [Atom](https://atom.io/) - 面向 21 世纪的极客文本编辑器。
### 文档
- [Microsoft Office](http://www.office.com/) - 微软办公软件。
- [WPS Office](https://www.wps.com/office-free) - 金山免费办公软件。
- [Calibre](http://calibre-ebook.com/) - 用于电子书管理和转换的强大软件。
- [福昕阅读器](http://www.foxitsoftware.cn/products/reader/) - 在全球拥有大量用户最优秀的国产软件之一。Ribbon 界面,支持手写签名、插入印章等。
### 效率提升
**【笔记】**
- [XMind](http://www.xmind.net/) - 优秀的思维导图。
- [OneNote](https://www.onenote.com/) - Windows 下综合评价非常高的笔记应用。
- [印象笔记](http://www.yinxiang.com/) - 老牌跨平台笔记工具,国际版 Evernote。一家立志于做百年公司的企业安全、可靠。
- [为知笔记](http://www.wiz.cn/index.html) - 越来越好的笔记应用,记录、查阅一切有价值的信息,同样跨平台支持。
- [有道云笔记](http://note.youdao.com/) - 网易旗下笔记工具,同样跨主流平台支持,文字、手写、录音、拍照多种记录方式,支持任意附件格式。
- [ShareX](https://getsharex.com/) - 你要的所有与截图、录屏相关的功能,这里都有了。
【快捷键】
- [AutoHotkey](https://autohotkey.com/) - Windows 平台的终极自动化脚本语言。
> 技巧:
>
> - https://www.jeffjade.com/2016/03/11/2016-03-11-autohotkey/
> - https://www.autohotkey.com/boards/viewtopic.php?f=29&t=4296
### 办公
- [有道词典](http://cidian.youdao.com/index.html) - 最好用的免费全能翻译软件。
- [Outlook](http://office.microsoft.com/zh-cn/outlook/) - 大名鼎鼎的 Microsoft Office 组件之一,除了电子邮件,还包含了日历、任务管理、联系人、记事本等功能。
- [Gmail](http://www.gmail.com/) - 功能上可以称为业界标杆,用户数量世界第一,或许你真的找不到比它更好的邮件系统。
- [Chrome](https://www.google.com/intl/zh-CN/chrome/browser/) - 最好的浏览器。
- [Teamviewer](http://www.teamviewer.com/Zhcn/index.aspx) - 专业、功能强大的远程控制软件。使用简单,对个人用户免费。
### 个性化
- [TranslucentTB](https://github.com/TranslucentTB/TranslucentTB) - 透明化你的 Windows 任务栏。
- [QTTabBar](http://qttabbar.wikidot.com/) - 通过多标签和额外的文件夹视图扩展资源管理器的功能。
- [Fences](https://www.stardock.com/products/fences/) - 管理桌面快捷方式。
## 参考资料
- https://github.com/Awesome-Windows/Awesome/blob/master/README-cn.md
- https://love.appinn.com/
- https://github.com/stackia/best-windows-apps

View File

@ -0,0 +1,7 @@
/**
* @see https://prettier.io/docs/en/options.html
* @see https://prettier.io/docs/en/configuration.html
*/
module.exports = {
tabWidth: 2, semi: false, singleQuote: true
}