Full Code of dunwu/linux-tutorial for AI

master b672dd042960 cached
351 files
742.6 KB
285.2k tokens
1 symbols
1 requests
Download .txt
Showing preview only (821K chars total). Download the full file or copy to clipboard to get everything.
Repository: dunwu/linux-tutorial
Branch: master
Commit: b672dd042960
Files: 351
Total size: 742.6 KB

Directory structure:
gitextract_eglus17c/

├── .editorconfig
├── .gitattributes
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── assets/
│   ├── docker.xmind
│   └── linux.xmind
├── codes/
│   ├── docker/
│   │   └── docker-compose-demo/
│   │       ├── Dockerfile
│   │       ├── app.py
│   │       ├── docker-compose.yml
│   │       └── run.sh
│   ├── expect/
│   │   └── 远程登录.sh
│   ├── linux/
│   │   ├── README.md
│   │   ├── build/
│   │   │   ├── Java应用运行脚本模板/
│   │   │   │   ├── lifecycle.sh
│   │   │   │   ├── start.sh
│   │   │   │   ├── stop.sh
│   │   │   │   └── utils.sh
│   │   │   ├── README.md
│   │   │   ├── helper.sh
│   │   │   ├── java-app-boot.sh
│   │   │   ├── java-app-release.sh
│   │   │   ├── java-app-run.sh
│   │   │   ├── js-app-release.sh
│   │   │   ├── main.sh
│   │   │   ├── spring-boot-run.sh
│   │   │   └── update-code.sh
│   │   ├── conf/
│   │   │   └── etc/
│   │   │       └── sysctl.conf
│   │   ├── download.sh
│   │   ├── dunwu-ops.sh
│   │   ├── dunwu-soft.sh
│   │   ├── dunwu-sys.sh
│   │   ├── libtest/
│   │   │   ├── README.md
│   │   │   ├── env-test.sh
│   │   │   ├── git-check.sh
│   │   │   ├── git-update.sh
│   │   │   └── nodejs-test.sh
│   │   ├── soft/
│   │   │   ├── README.md
│   │   │   ├── arthas-install.sh
│   │   │   ├── config/
│   │   │   │   ├── fastdfs/
│   │   │   │   │   ├── client.conf
│   │   │   │   │   ├── storage.conf
│   │   │   │   │   └── tracker.conf
│   │   │   │   ├── mysql/
│   │   │   │   │   └── my.cnf
│   │   │   │   ├── nginx/
│   │   │   │   │   ├── conf/
│   │   │   │   │   │   └── fdfs.conf
│   │   │   │   │   ├── nginx.conf
│   │   │   │   │   └── nginx.service
│   │   │   │   ├── redis/
│   │   │   │   │   ├── cluster/
│   │   │   │   │   │   ├── 27001/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 27002/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 27003/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 27004/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 27005/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 27006/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 7001/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7002/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7003/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7004/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7005/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7006/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7007/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7008/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7009/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7010/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7011/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7012/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── README.md
│   │   │   │   │   │   ├── redis-cluster.sh
│   │   │   │   │   │   ├── redis-cluster2.sh
│   │   │   │   │   │   ├── start-cluster.sh
│   │   │   │   │   │   ├── start-cluster2.sh
│   │   │   │   │   │   └── start-sentinel.sh
│   │   │   │   │   ├── redis.conf
│   │   │   │   │   └── redis.service
│   │   │   │   └── settings-aliyun.xml
│   │   │   ├── docker-install.sh
│   │   │   ├── elk/
│   │   │   │   ├── boot-elk.sh
│   │   │   │   ├── config/
│   │   │   │   │   ├── filebeat.yml
│   │   │   │   │   ├── logback.xml
│   │   │   │   │   └── logstash.conf
│   │   │   │   ├── install-elk.sh
│   │   │   │   ├── install_elasticserch.sh
│   │   │   │   ├── install_filebeat.sh
│   │   │   │   ├── install_kibana.sh
│   │   │   │   └── install_logstash.sh
│   │   │   ├── fastdfs-install.sh
│   │   │   ├── gitlab/
│   │   │   │   ├── gitlab-backup.sh
│   │   │   │   └── gitlab.sh
│   │   │   ├── gitlab-install.sh
│   │   │   ├── install_grafana.sh
│   │   │   ├── jdk8-install.sh
│   │   │   ├── jenkins-install.sh
│   │   │   ├── kafka-install.sh
│   │   │   ├── lib/
│   │   │   │   ├── docker.sh
│   │   │   │   ├── file.sh
│   │   │   │   ├── git.sh
│   │   │   │   ├── java.sh
│   │   │   │   ├── maven.sh
│   │   │   │   ├── mysql.sh
│   │   │   │   ├── net.sh
│   │   │   │   ├── nodejs.sh
│   │   │   │   ├── string.sh
│   │   │   │   └── utils.sh
│   │   │   ├── maven-install.sh
│   │   │   ├── mongodb-install.sh
│   │   │   ├── mysql-backup.sh
│   │   │   ├── mysql-install.sh
│   │   │   ├── mysql-recovery.sh
│   │   │   ├── nacos-install.sh
│   │   │   ├── nexus-install.sh
│   │   │   ├── nginx-install.sh
│   │   │   ├── nodejs-install.sh
│   │   │   ├── redis-install.sh
│   │   │   ├── rocketmq-install.sh
│   │   │   ├── tomcat8-install.sh
│   │   │   ├── zookeeper-install.sh
│   │   │   ├── zsh/
│   │   │   │   └── oh-my-zsh-install.sh
│   │   │   └── zsh-install.sh
│   │   ├── sys/
│   │   │   ├── README.md
│   │   │   ├── change-yum-repo.sh
│   │   │   ├── install-libs.sh
│   │   │   ├── install-tools.sh
│   │   │   ├── set-dns.sh
│   │   │   ├── set-ntp.sh
│   │   │   ├── stop-firewall.sh
│   │   │   ├── sys-settings.sh
│   │   │   ├── syscheck.sh
│   │   │   └── yum/
│   │   │       ├── Centos-5.repo
│   │   │       ├── Centos-6.repo
│   │   │       └── Centos-7.repo
│   │   └── tool/
│   │       ├── Autoinstall_ELK_V1.3.sh
│   │       ├── Cpu_Limit.sh
│   │       ├── Custom_Rm.sh
│   │       ├── Daily_Archive.sh
│   │       ├── Hourly_Archive.sh
│   │       ├── gitcheck
│   │       ├── 删除用户脚本.sh
│   │       └── 查看指定目录磁盘使用情况.sh
│   └── shell/
│       ├── README.md
│       ├── lib/
│       │   └── env.sh
│       ├── mysql/
│       │   ├── SQL批处理执行脚本.sh
│       │   ├── 向数据库中插入数据.sh
│       │   ├── 格式化输出数据.sh
│       │   └── 连接数据库并发送命令.sh
│       ├── 基本脚本/
│       │   ├── echo示例.sh
│       │   ├── exit命令.sh
│       │   ├── printf示例.sh
│       │   ├── 使用expr执行数学运算.sh
│       │   ├── 使用内联重定向计算表达式.sh
│       │   ├── 使用方括号执行数学运算.sh
│       │   ├── 反引号的使用.sh
│       │   ├── 变量使用示例.sh
│       │   ├── 在脚本中使用bc.sh
│       │   ├── 字符串使用示例.sh
│       │   ├── 数组使用示例.sh
│       │   ├── 显示时间和登录者.sh
│       │   ├── 显示系统变量和转义字符.sh
│       │   ├── 注释示例.sh
│       │   └── 通过反引号获得当前日期并生成唯一文件名.sh
│       ├── 控制/
│       │   ├── 定时执行脚本.sh
│       │   ├── 捕捉信号.sh
│       │   ├── 捕捉脚本的退出.sh
│       │   └── 移除捕捉.sh
│       ├── 操作符/
│       │   ├── 关系运算符.sh
│       │   ├── 字符串运算符.sh
│       │   ├── 布尔运算符.sh
│       │   ├── 文件测试运算符.sh
│       │   ├── 算术运算符.sh
│       │   └── 逻辑运算符.sh
│       ├── 文件操作/
│       │   ├── log.txt
│       │   ├── 创建临时文件.sh
│       │   ├── 创建临时目录.sh
│       │   ├── 文件路径操作.sh
│       │   ├── 目录基本操作.sh
│       │   └── 读文件.sh
│       ├── 查找替换文本/
│       │   ├── gawk/
│       │   │   ├── gawk.sh
│       │   │   ├── gawk函数库
│       │   │   ├── gawk脚本
│       │   │   ├── script
│       │   │   ├── test
│       │   │   ├── 使用变量.sh
│       │   │   ├── 使用模式,结构化命令.sh
│       │   │   ├── 自定义函数.sh
│       │   │   ├── 调用函数库和脚本.sh
│       │   │   └── 输出.sh
│       │   ├── grep.sh
│       │   ├── regex/
│       │   │   ├── 目录文件计数.sh
│       │   │   └── 邮件验证.sh
│       │   └── sed/
│       │       ├── sed文件操作.sh
│       │       ├── sed编辑器基础.sh
│       │       ├── test
│       │       ├── 保持空间.sh
│       │       ├── 删除指定的空白行和删除html标签.sh
│       │       ├── 在脚本中使用sed.sh
│       │       ├── 排除命令.sh
│       │       ├── 模式替代.sh
│       │       ├── 测试.sh
│       │       ├── 给文件中的行编号.sh
│       │       ├── 跳转.sh
│       │       ├── 输出末尾指定行数的数据.sh
│       │       └── 重定向sed输出.sh
│       ├── 系统管理/
│       │   ├── 控制远程服务器执行指令.sh
│       │   └── 系统用户管理.sh
│       ├── 脚本函数/
│       │   ├── lib.sh
│       │   ├── 从函数返回数组.sh
│       │   ├── 使用return命令.sh
│       │   ├── 使用全局变量带来的问题.sh
│       │   ├── 使用函数输出.sh
│       │   ├── 使用命令行中传递的参数.sh
│       │   ├── 使用局部变量.sh
│       │   ├── 使用库函数.sh
│       │   ├── 全局变量.sh
│       │   ├── 函数入参.sh
│       │   ├── 函数入参2.sh
│       │   ├── 函数基本示例.sh
│       │   ├── 函数基本示例2.sh
│       │   ├── 函数递归.sh
│       │   ├── 在函数中使用参数.sh
│       │   ├── 想函数传数组数据.sh
│       │   ├── 累加数组中的值.sh
│       │   └── 默认退出状态码.sh
│       ├── 菜单/
│       │   ├── 使用msgbox部件.sh
│       │   ├── 使用select命令.sh
│       │   ├── 使用脚本菜单.sh
│       │   └── 在脚本中使用dialog命令.sh
│       ├── 输入和输出/
│       │   ├── test
│       │   ├── test1
│       │   ├── 临时重定向.sh
│       │   ├── 使用getopts.sh
│       │   ├── 使用getopts处理选项和参数.sh
│       │   ├── 使用getopt命令.sh
│       │   ├── 使用shift命令.sh
│       │   ├── 免密码传输.sh
│       │   ├── 分离参数和选项.sh
│       │   ├── 列出当前脚本打开的文件描述符.sh
│       │   ├── 创建自己的重定向/
│       │   │   ├── 从以重定向的文件描述符中恢复.sh
│       │   │   ├── 关闭文件描述符.sh
│       │   │   ├── 创建读写文件描述符.sh
│       │   │   ├── 创建输入文件描述符.sh
│       │   │   └── 创建输出文件描述符.sh
│       │   ├── 参数计数.sh
│       │   ├── 在脚本中使用重定向输入.sh
│       │   ├── 处理带值的选项.sh
│       │   ├── 处理简单选项.sh
│       │   ├── 快速清除文件或日志.sh
│       │   ├── 抓取所有数据.sh
│       │   ├── 永久重定向.sh
│       │   ├── 测试.txt
│       │   ├── 获取用户输入.sh
│       │   ├── 记录信息.sh
│       │   ├── 读取参数.sh
│       │   ├── 读取多个命令行参数.sh
│       │   ├── 读取程序名.sh
│       │   ├── 读取选择参数.sh
│       │   ├── 超时和输入计数.sh
│       │   └── 隐藏方式读取数据.sh
│       ├── 进阶脚本/
│       │   ├── 创建捕捉脚本.sh
│       │   ├── 开启debug模式.sh
│       │   ├── 查看uptime获取在线用户数.sh
│       │   ├── 生成报告脚本-基于创建捕捉脚本.sh
│       │   ├── 系统快照报告.sh
│       │   ├── 输出颜色.sh
│       │   └── 问题跟踪数据库/
│       │       ├── Update_Problem.sh
│       │       ├── 查找问题.sh
│       │       └── 记录问题.sh
│       └── 逻辑控制/
│           ├── bash-shell无法处理浮点数.sh
│           ├── break示例.sh
│           ├── case示例.sh
│           ├── continue示例.sh
│           ├── for循环示例.sh
│           ├── if-elif-else示例.sh
│           ├── output.txt
│           ├── select菜单示例.sh
│           ├── until示例.sh
│           ├── while循环示例.sh
│           ├── 从命令读取值.sh
│           ├── 使用双圆括号.sh
│           ├── 使用双方括号.sh
│           ├── 使用大于小于号.sh
│           ├── 使用嵌套循环并修改IFS.sh
│           ├── 使用管道或重定向.sh
│           ├── 使用通配符处理目录.sh
│           ├── 注意test大小写顺序和sort不同.sh
│           └── 读取里表中复杂的值.sh
├── docs/
│   ├── .remarkrc
│   ├── .textlint.terms.json
│   ├── .textlintrc.js
│   ├── .vuepress/
│   │   ├── config.js
│   │   └── enhanceApp.js
│   ├── README.md
│   ├── docker/
│   │   ├── README.md
│   │   ├── docker-cheat-sheet.md
│   │   ├── docker-compose.md
│   │   ├── docker-dockerfile.md
│   │   ├── docker-quickstart.md
│   │   ├── docker.xmind
│   │   ├── kubernetes.md
│   │   └── service/
│   │       ├── docker-install-mysql.md
│   │       └── docker-install-nginx.md
│   ├── linux/
│   │   ├── cli/
│   │   │   ├── README.md
│   │   │   ├── free.md
│   │   │   ├── grep.md
│   │   │   ├── iostat.md
│   │   │   ├── iotop.md
│   │   │   ├── linux-cli-dir.md
│   │   │   ├── linux-cli-file-compress.md
│   │   │   ├── linux-cli-file.md
│   │   │   ├── linux-cli-hardware.md
│   │   │   ├── linux-cli-help.md
│   │   │   ├── linux-cli-net.md
│   │   │   ├── linux-cli-software.md
│   │   │   ├── linux-cli-system.md
│   │   │   ├── linux-cli-user.md
│   │   │   ├── scp.md
│   │   │   ├── top.md
│   │   │   ├── vmstat.md
│   │   │   └── 命令行的艺术.md
│   │   ├── expect.md
│   │   ├── ops/
│   │   │   ├── README.md
│   │   │   ├── crontab.md
│   │   │   ├── firewalld.md
│   │   │   ├── iptables.md
│   │   │   ├── network-ops.md
│   │   │   ├── ntp.md
│   │   │   ├── samba.md
│   │   │   ├── systemd.md
│   │   │   ├── vim.md
│   │   │   └── zsh.md
│   │   └── soft/
│   │       ├── README.md
│   │       ├── apollo/
│   │       │   ├── README.md
│   │       │   └── apollo.xmind
│   │       ├── elastic/
│   │       │   ├── README.md
│   │       │   ├── elastic-beats.md
│   │       │   ├── elastic-kibana.md
│   │       │   ├── elastic-logstash.md
│   │       │   └── elastic-quickstart.md
│   │       ├── fastdfs.md
│   │       ├── gitlab-ops.md
│   │       ├── jdk-install.md
│   │       ├── jenkins-ops.md
│   │       ├── kafka-install.md
│   │       ├── maven-install.md
│   │       ├── mongodb-ops.md
│   │       ├── nacos-install.md
│   │       ├── nexus-ops.md
│   │       ├── nodejs-install.md
│   │       ├── rocketmq-install.md
│   │       ├── svn-ops.md
│   │       ├── tomcat-install.md
│   │       └── yapi-ops.md
│   ├── mac/
│   │   └── soft/
│   │       └── ruby-install.md
│   └── package.json
└── scripts/
    └── deploy.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# EditorConfig 用于在 IDE 中检查代码的基本 Code Style
# @see: https://editorconfig.org/

# 配置说明:
# 所有文件换行使用 Unix 风格(LF),*.bat 文件使用 Windows 风格(CRLF)
# java / sh 文件缩进 4 个空格,其他所有文件缩进 2 个空格

root = true

[*]
end_of_line = lf
indent_size = 2
indent_style = space
max_line_length = 120
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{bat, cmd}]
end_of_line = crlf

[*.{java, gradle, groovy, kt, sh}]
indent_size = 4

[*.md]
max_line_length = 0
trim_trailing_whitespace = false


================================================
FILE: .gitattributes
================================================
* text=auto eol=lf

# plan text
*.txt text
*.java text
*.scala text
*.groovy text
*.gradle text
*.xml text
*.xsd text
*.tld text
*.yaml text
*.yml text
*.wsdd text
*.wsdl text
*.jsp text
*.jspf text
*.js text
*.jsx text
*.json text
*.css text
*.less text
*.sql text
*.properties text

# unix style
*.sh text eol=lf

# win style
*.bat text eol=crlf

# don't handle
*.der -text
*.jks -text
*.pfx -text
*.map -text
*.patch -text
*.dat -text
*.data -text
*.db -text

# binary
*.jar binary
*.war binary
*.zip binary
*.tar binary
*.tar.gz binary
*.gz binary
*.apk binary
*.bin binary
*.exe binary

# images
*.png binary
*.jpg binary
*.ico binary
*.gif binary

# medias
*.mp3 binary
*.swf binary

# fonts
*.eot binary
*.svg binary
*.ttf binary
*.woff binary

# others
*.pdf binary
*.doc binary
*.docx binary
*.ppt binary
*.pptx binary
*.xls binary
*.xlsx binary
*.xmind binary


================================================
FILE: .gitignore
================================================
# ---------------------------------------------------------------------
# more gitignore templates see https://github.com/github/gitignore
# ---------------------------------------------------------------------

# ------------------------------- java -------------------------------
# compiled folders
classes
target
logs
.mtj.tmp/

# compiled files
*.class

# bluej files
*.ctxt

# package files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs
hs_err_pid*

# maven plugin temp files
.flattened-pom.xml
package-lock.json
pnpm-lock.yaml

# ------------------------------- javascript -------------------------------
# dependencies
node_modules

# temp folders
.temp
dist
_book
_jsdoc

# temp files
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
bundle*.js
book.pdf

# ------------------------------- intellij -------------------------------
.idea
*.iml

# ------------------------------- eclipse -------------------------------
.classpath
.project


================================================
FILE: .travis.yml
================================================
# 持续集成 CI
# @see https://docs.travis-ci.com/user/tutorial/

language: node_js

sudo: required

node_js: '16.13.0'

branches:
  only:
    - master

before_install:
  - export TZ=Asia/Shanghai

script: bash ./scripts/deploy.sh

notifications:
  email:
    recipients:
      - forbreak@163.com
    on_success: change
    on_failure: always


================================================
FILE: LICENSE
================================================
Attribution-ShareAlike 4.0 International

=======================================================================

Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.

Using Creative Commons Public Licenses

Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.

     Considerations for licensors: Our public licenses are
     intended for use by those authorized to give the public
     permission to use material in ways otherwise restricted by
     copyright and certain other rights. Our licenses are
     irrevocable. Licensors should read and understand the terms
     and conditions of the license they choose before applying it.
     Licensors should also secure all rights necessary before
     applying our licenses so that the public can reuse the
     material as expected. Licensors should clearly mark any
     material not subject to the license. This includes other CC-
     licensed material, or material used under an exception or
     limitation to copyright. More considerations for licensors:
	wiki.creativecommons.org/Considerations_for_licensors

     Considerations for the public: By using one of our public
     licenses, a licensor grants the public permission to use the
     licensed material under specified terms and conditions. If
     the licensor's permission is not necessary for any reason--for
     example, because of any applicable exception or limitation to
     copyright--then that use is not regulated by the license. Our
     licenses grant only permissions under copyright and certain
     other rights that a licensor has authority to grant. Use of
     the licensed material may still be restricted for other
     reasons, including because others have copyright or other
     rights in the material. A licensor may make special requests,
     such as asking that all changes be marked or described.
     Although not required by our licenses, you are encouraged to
     respect those requests where reasonable. More_considerations
     for the public:
	wiki.creativecommons.org/Considerations_for_licensees

=======================================================================

Creative Commons Attribution-ShareAlike 4.0 International Public
License

By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-ShareAlike 4.0 International Public License ("Public
License"). To the extent this Public License may be interpreted as a
contract, You are granted the Licensed Rights in consideration of Your
acceptance of these terms and conditions, and the Licensor grants You
such rights in consideration of benefits the Licensor receives from
making the Licensed Material available under these terms and
conditions.


Section 1 -- Definitions.

  a. Adapted Material means material subject to Copyright and Similar
     Rights that is derived from or based upon the Licensed Material
     and in which the Licensed Material is translated, altered,
     arranged, transformed, or otherwise modified in a manner requiring
     permission under the Copyright and Similar Rights held by the
     Licensor. For purposes of this Public License, where the Licensed
     Material is a musical work, performance, or sound recording,
     Adapted Material is always produced where the Licensed Material is
     synched in timed relation with a moving image.

  b. Adapter's License means the license You apply to Your Copyright
     and Similar Rights in Your contributions to Adapted Material in
     accordance with the terms and conditions of this Public License.

  c. BY-SA Compatible License means a license listed at
     creativecommons.org/compatiblelicenses, approved by Creative
     Commons as essentially the equivalent of this Public License.

  d. Copyright and Similar Rights means copyright and/or similar rights
     closely related to copyright including, without limitation,
     performance, broadcast, sound recording, and Sui Generis Database
     Rights, without regard to how the rights are labeled or
     categorized. For purposes of this Public License, the rights
     specified in Section 2(b)(1)-(2) are not Copyright and Similar
     Rights.

  e. Effective Technological Measures means those measures that, in the
     absence of proper authority, may not be circumvented under laws
     fulfilling obligations under Article 11 of the WIPO Copyright
     Treaty adopted on December 20, 1996, and/or similar international
     agreements.

  f. Exceptions and Limitations means fair use, fair dealing, and/or
     any other exception or limitation to Copyright and Similar Rights
     that applies to Your use of the Licensed Material.

  g. License Elements means the license attributes listed in the name
     of a Creative Commons Public License. The License Elements of this
     Public License are Attribution and ShareAlike.

  h. Licensed Material means the artistic or literary work, database,
     or other material to which the Licensor applied this Public
     License.

  i. Licensed Rights means the rights granted to You subject to the
     terms and conditions of this Public License, which are limited to
     all Copyright and Similar Rights that apply to Your use of the
     Licensed Material and that the Licensor has authority to license.

  j. Licensor means the individual(s) or entity(ies) granting rights
     under this Public License.

  k. Share means to provide material to the public by any means or
     process that requires permission under the Licensed Rights, such
     as reproduction, public display, public performance, distribution,
     dissemination, communication, or importation, and to make material
     available to the public including in ways that members of the
     public may access the material from a place and at a time
     individually chosen by them.

  l. Sui Generis Database Rights means rights other than copyright
     resulting from Directive 96/9/EC of the European Parliament and of
     the Council of 11 March 1996 on the legal protection of databases,
     as amended and/or succeeded, as well as other essentially
     equivalent rights anywhere in the world.

  m. You means the individual or entity exercising the Licensed Rights
     under this Public License. Your has a corresponding meaning.


Section 2 -- Scope.

  a. License grant.

       1. Subject to the terms and conditions of this Public License,
          the Licensor hereby grants You a worldwide, royalty-free,
          non-sublicensable, non-exclusive, irrevocable license to
          exercise the Licensed Rights in the Licensed Material to:

            a. reproduce and Share the Licensed Material, in whole or
               in part; and

            b. produce, reproduce, and Share Adapted Material.

       2. Exceptions and Limitations. For the avoidance of doubt, where
          Exceptions and Limitations apply to Your use, this Public
          License does not apply, and You do not need to comply with
          its terms and conditions.

       3. Term. The term of this Public License is specified in Section
          6(a).

       4. Media and formats; technical modifications allowed. The
          Licensor authorizes You to exercise the Licensed Rights in
          all media and formats whether now known or hereafter created,
          and to make technical modifications necessary to do so. The
          Licensor waives and/or agrees not to assert any right or
          authority to forbid You from making technical modifications
          necessary to exercise the Licensed Rights, including
          technical modifications necessary to circumvent Effective
          Technological Measures. For purposes of this Public License,
          simply making modifications authorized by this Section 2(a)
          (4) never produces Adapted Material.

       5. Downstream recipients.

            a. Offer from the Licensor -- Licensed Material. Every
               recipient of the Licensed Material automatically
               receives an offer from the Licensor to exercise the
               Licensed Rights under the terms and conditions of this
               Public License.

            b. Additional offer from the Licensor -- Adapted Material.
               Every recipient of Adapted Material from You
               automatically receives an offer from the Licensor to
               exercise the Licensed Rights in the Adapted Material
               under the conditions of the Adapter's License You apply.

            c. No downstream restrictions. You may not offer or impose
               any additional or different terms or conditions on, or
               apply any Effective Technological Measures to, the
               Licensed Material if doing so restricts exercise of the
               Licensed Rights by any recipient of the Licensed
               Material.

       6. No endorsement. Nothing in this Public License constitutes or
          may be construed as permission to assert or imply that You
          are, or that Your use of the Licensed Material is, connected
          with, or sponsored, endorsed, or granted official status by,
          the Licensor or others designated to receive attribution as
          provided in Section 3(a)(1)(A)(i).

  b. Other rights.

       1. Moral rights, such as the right of integrity, are not
          licensed under this Public License, nor are publicity,
          privacy, and/or other similar personality rights; however, to
          the extent possible, the Licensor waives and/or agrees not to
          assert any such rights held by the Licensor to the limited
          extent necessary to allow You to exercise the Licensed
          Rights, but not otherwise.

       2. Patent and trademark rights are not licensed under this
          Public License.

       3. To the extent possible, the Licensor waives any right to
          collect royalties from You for the exercise of the Licensed
          Rights, whether directly or through a collecting society
          under any voluntary or waivable statutory or compulsory
          licensing scheme. In all other cases the Licensor expressly
          reserves any right to collect such royalties.


Section 3 -- License Conditions.

Your exercise of the Licensed Rights is expressly made subject to the
following conditions.

  a. Attribution.

       1. If You Share the Licensed Material (including in modified
          form), You must:

            a. retain the following if it is supplied by the Licensor
               with the Licensed Material:

                 i. identification of the creator(s) of the Licensed
                    Material and any others designated to receive
                    attribution, in any reasonable manner requested by
                    the Licensor (including by pseudonym if
                    designated);

                ii. a copyright notice;

               iii. a notice that refers to this Public License;

                iv. a notice that refers to the disclaimer of
                    warranties;

                 v. a URI or hyperlink to the Licensed Material to the
                    extent reasonably practicable;

            b. indicate if You modified the Licensed Material and
               retain an indication of any previous modifications; and

            c. indicate the Licensed Material is licensed under this
               Public License, and include the text of, or the URI or
               hyperlink to, this Public License.

       2. You may satisfy the conditions in Section 3(a)(1) in any
          reasonable manner based on the medium, means, and context in
          which You Share the Licensed Material. For example, it may be
          reasonable to satisfy the conditions by providing a URI or
          hyperlink to a resource that includes the required
          information.

       3. If requested by the Licensor, You must remove any of the
          information required by Section 3(a)(1)(A) to the extent
          reasonably practicable.

  b. ShareAlike.

     In addition to the conditions in Section 3(a), if You Share
     Adapted Material You produce, the following conditions also apply.

       1. The Adapter's License You apply must be a Creative Commons
          license with the same License Elements, this version or
          later, or a BY-SA Compatible License.

       2. You must include the text of, or the URI or hyperlink to, the
          Adapter's License You apply. You may satisfy this condition
          in any reasonable manner based on the medium, means, and
          context in which You Share Adapted Material.

       3. You may not offer or impose any additional or different terms
          or conditions on, or apply any Effective Technological
          Measures to, Adapted Material that restrict exercise of the
          rights granted under the Adapter's License You apply.


Section 4 -- Sui Generis Database Rights.

Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:

  a. for the avoidance of doubt, Section 2(a)(1) grants You the right
     to extract, reuse, reproduce, and Share all or a substantial
     portion of the contents of the database;

  b. if You include all or a substantial portion of the database
     contents in a database in which You have Sui Generis Database
     Rights, then the database in which You have Sui Generis Database
     Rights (but not its individual contents) is Adapted Material,

     including for purposes of Section 3(b); and
  c. You must comply with the conditions in Section 3(a) if You Share
     all or a substantial portion of the contents of the database.

For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.


Section 5 -- Disclaimer of Warranties and Limitation of Liability.

  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.

  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.

  c. The disclaimer of warranties and limitation of liability provided
     above shall be interpreted in a manner that, to the extent
     possible, most closely approximates an absolute disclaimer and
     waiver of all liability.


Section 6 -- Term and Termination.

  a. This Public License applies for the term of the Copyright and
     Similar Rights licensed here. However, if You fail to comply with
     this Public License, then Your rights under this Public License
     terminate automatically.

  b. Where Your right to use the Licensed Material has terminated under
     Section 6(a), it reinstates:

       1. automatically as of the date the violation is cured, provided
          it is cured within 30 days of Your discovery of the
          violation; or

       2. upon express reinstatement by the Licensor.

     For the avoidance of doubt, this Section 6(b) does not affect any
     right the Licensor may have to seek remedies for Your violations
     of this Public License.

  c. For the avoidance of doubt, the Licensor may also offer the
     Licensed Material under separate terms or conditions or stop
     distributing the Licensed Material at any time; however, doing so
     will not terminate this Public License.

  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
     License.


Section 7 -- Other Terms and Conditions.

  a. The Licensor shall not be bound by any additional or different
     terms or conditions communicated by You unless expressly agreed.

  b. Any arrangements, understandings, or agreements regarding the
     Licensed Material not stated herein are separate from and
     independent of the terms and conditions of this Public License.


Section 8 -- Interpretation.

  a. For the avoidance of doubt, this Public License does not, and
     shall not be interpreted to, reduce, limit, restrict, or impose
     conditions on any use of the Licensed Material that could lawfully
     be made without permission under this Public License.

  b. To the extent possible, if any provision of this Public License is
     deemed unenforceable, it shall be automatically reformed to the
     minimum extent necessary to make it enforceable. If the provision
     cannot be reformed, it shall be severed from this Public License
     without affecting the enforceability of the remaining terms and
     conditions.

  c. No term or condition of this Public License will be waived and no
     failure to comply consented to unless expressly agreed to by the
     Licensor.

  d. Nothing in this Public License constitutes or may be interpreted
     as a limitation upon, or waiver of, any privileges and immunities
     that apply to the Licensor or You, including from the legal
     processes of any jurisdiction or authority.


=======================================================================

Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.

Creative Commons may be contacted at creativecommons.org.


================================================
FILE: README.md
================================================
<p align="center">
    <a href="https://dunwu.github.io/linux-tutorial/" target="_blank" rel="noopener noreferrer">
        <img src="https://raw.githubusercontent.com/dunwu/images/master/common/logo/linux.svg" alt="logo" width="100px">
    </a>
</p>

<p align="center">
    <img src="https://badgen.net/github/license/dunwu/linux-tutorial" alt="license">
    <img src="https://travis-ci.com/dunwu/linux-tutorial.svg?branch=master" alt="build">
</p>

<h1 align="center">linux-tutorial</h1>

> 📚 **linux-tutorial** 是一个 Linux 教程。
>
> - 🔁 项目同步维护:[Github](https://github.com/dunwu/linux-tutorial/) | [Gitee](https://gitee.com/turnon/linux-tutorial/)
> - 📖 电子书阅读:[Github Pages](https://dunwu.github.io/linux-tutorial/) | [Gitee Pages](http://turnon.gitee.io/linux-tutorial/)

## 📖 内容

### Linux 命令

> 学习 Linux 的第一步:当然是从 [Linux 命令](docs/linux/cli/README.md) 入手了。

- [查看 Linux 命令帮助信息](docs/linux/cli/linux-cli-help.md) - 关键词:`help`, `whatis`, `info`, `which`, `whereis`, `man`
- [Linux 文件目录管理](docs/linux/cli/linux-cli-dir.md) - 关键词:`cd`, `ls`, `pwd`, `mkdir`, `rmdir`, `tree`, `touch`, `ln`, `rename`, `stat`, `file`, `chmod`, `chown`, `locate`, `find`, `cp`, `mv`, `rm`
- [Linux 文件内容查看命令](docs/linux/cli/linux-cli-file.md) - 关键词:`cat`, `head`, `tail`, `more`, `less`, `sed`, `vi`, `grep`
- [Linux 文件压缩和解压](docs/linux/cli/linux-cli-file-compress.md) - 关键词:`tar`, `gzip`, `zip`, `unzip`
- [Linux 用户管理](docs/linux/cli/linux-cli-user.md) - 关键词:`groupadd`, `groupdel`, `groupmod`, `useradd`, `userdel`, `usermod`, `passwd`, `su`, `sudo`
- [Linux 系统管理](docs/linux/cli/linux-cli-system.md) - 关键词:`reboot`, `exit`, `shutdown`, `date`, `mount`, `umount`, `ps`, `kill`, `systemctl`, `service`, `crontab`
- [Linux 网络管理](docs/linux/cli/linux-cli-net.md) - 关键词:关键词:`curl`, `wget`, `telnet`, `ip`, `hostname`, `ifconfig`, `route`, `ssh`, `ssh-keygen`, `firewalld`, `iptables`, `host`, `nslookup`, `nc`/`netcat`, `ping`, `traceroute`, `netstat`
- [Linux 硬件管理](docs/linux/cli/linux-cli-hardware.md) - 关键词:`df`, `du`, `top`, `free`, `iotop`
- [Linux 软件管理](docs/linux/cli/linux-cli-software.md) - 关键词:`rpm`, `yum`, `apt-get`

### Linux 运维

> Linux 系统的常见运维工作。

- [网络运维](docs/linux/ops/network-ops.md)
- [Samba](docs/linux/ops/samba.md)
- [NTP](docs/linux/ops/ntp.md)
- [Firewalld](docs/linux/ops/firewalld.md)
- [Crontab](docs/linux/ops/crontab.md)
- [Systemd](docs/linux/ops/systemd.md)
- [Vim](docs/linux/ops/vim.md)
- [Iptables](docs/linux/ops/iptables.md)
- [oh-my-zsh](docs/linux/ops/zsh.md)

### 软件运维

> 部署在 Linux 系统上的软件运维。
>
> 配套安装脚本:⌨ [软件运维配置脚本集合](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux/soft)

- 开发环境
  - [JDK 安装](docs/linux/soft/jdk-install.md)
  - [Maven 安装](docs/linux/soft/maven-install.md)
  - [Nodejs 安装](docs/linux/soft/nodejs-install.md)
- 开发工具
  - [Nexus 运维](docs/linux/soft/nexus-ops.md)
  - [Gitlab 运维](docs/linux/soft/gitlab-ops.md)
  - [Jenkins 运维](docs/linux/soft/jenkins-ops.md)
  - [Svn 运维](docs/linux/soft/svn-ops.md)
  - [YApi 运维](docs/linux/soft/yapi-ops.md)
- 中间件服务
  - [Elastic 运维](docs/linux/soft/elastic)
  - [Kafka 运维](docs/linux/soft/kafka-install.md)
  - [RocketMQ 运维](docs/linux/soft/rocketmq-install.md)
  - [Zookeeper 运维](https://github.com/dunwu/javatech/blob/master/docs/technology/monitor/zookeeper-ops.md)
  - [Nacos 运维](docs/linux/soft/nacos-install.md)
- 服务器
  - [Nginx 教程](https://github.com/dunwu/nginx-tutorial) 📚
  - [Tomcat 运维](docs/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 快速入门](docs/docker/docker-quickstart.md)
- [Dockerfile 最佳实践](docs/docker/docker-dockerfile.md)
- [Docker Cheat Sheet](docs/docker/docker-cheat-sheet.md)
- [Kubernetes 应用指南](docs/docker/kubernetes.md)

### 其他

- [一篇文章让你彻底掌握 Python](https://dunwu.github.io/blog/pages/ef501b/)
- [一篇文章让你彻底掌握 Shell](https://dunwu.github.io/blog/pages/ea6ae1/)
- [如何优雅的玩转 Git](https://dunwu.github.io/blog/pages/2fc8b1/)

## ⌨ 脚本

### Shell 脚本大全

**Shell 脚本大全** 精心收集、整理了 Linux 环境下的常见 Shell 脚本操作片段。

源码:[**Shell 脚本大全**](https://github.com/dunwu/linux-tutorial/tree/master/codes/shell)

### CentOS 运维脚本集合

本人作为一名 Java 后端,苦于经常在 CentOS 环境上开荒虚拟机。为提高效率,写了一套 Shell 脚本,提供如下功能:安装常用 lib 库、命令工具、设置 DNS、NTP、配置国内 yum 源、一键安装常用软件等。

源码:[**CentOS 常规操作运维脚本集合**](https://github.com/dunwu/linux-tutorial/tree/master/codes/linux)

## 📚 资料

- **Linux 命令**
  - [命令行的艺术](https://github.com/jlevy/the-art-of-command-line/blob/master/README-zh.md)
  - [Linux 命令大全](https://man.linuxde.net/)
  - [linux-command](https://github.com/jaywcjlove/linux-command)
- **社区网站**
  - [Linux 中国](https://linux.cn/) - 各种资讯、文章、技术
  - [LabEx 中国](https://labex.io/) - 免费提供了 Linux 在线环境,不用在自己机子上装系统也可以学习 Linux,超方便实用。
  - [鸟哥的 linux 私房菜](http://linux.vbird.org/) - 非常适合 Linux 入门初学者看的教程。
  - [Linux 公社](http://www.linuxidc.com/) - Linux 相关的新闻、教程、主题、壁纸都有。
  - [Linux Today](http://www.linuxde.net) - Linux 新闻资讯发布,Linux 职业技术学习!。
- **知识相关**
  - [Linux 思维导图整理](http://www.jianshu.com/p/59f759207862)
  - [Linux 初学者进阶学习资源整理](http://www.jianshu.com/p/fe2a790b41eb)
  - [Linux 快速入门(动手实验)](https://labex.io/zh/courses/quick-start-with-linux)
  - [【译】Linux 概念架构的理解](http://www.jianshu.com/p/c5ae8f061cfe) [En](http://oss.org.cn/ossdocs/linux/kernel/a1/index.html)
  - [Linux 守护进程的启动方法](http://www.ruanyifeng.com/blog/2016/02/linux-daemon.html)
  - [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)
- **软件工具**
  - [超赞的 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)
  - [提高 Linux 开发效率的 5 个工具](http://www.codeceo.com/article/5-linux-productivity-tools.html)
  - [你要了解的 11 款面向 Linux 系统的一流备份实用工具](http://os.51cto.com/art/201603/508027.htm)
  - [16 个很有用的在线工具](http://www.simlinux.com/archives/264.html)
  - Adobe 软件的最佳替代品 [原文在这里](https://linux.cn/article-8928-1.html)
    - [Evince (Adobe Acrobat Reader)](https://wiki.gnome.org/Apps/Evince) 一个“支持多种文档格式的文档查看器”,可以查看 PDF,还支持各种漫画书格式
    - [Pixlr (Adobe Photoshop)](https://pixlr.com/) 一个强大的图像编辑工具
    - [Inkscape (Adobe Illustrator)](https://inkscape.org/zh/) 一个专业的矢量图形编辑器
    - [Pinegrow Web Editor (Adobe Dreamweaver)](https://pinegrow.com/) 一个可视化编辑制作 HTML 网站
    - [Scribus (Adobe InDesign)](https://www.scribus.net/) 一个开源电子杂志制作软件
    - [Webflow (Adobe Muse)](https://webflow.com/) 一款可以帮助用户不用编码就可以快速创建网站的谷歌浏览器插件。
    - [Tupi (Adobe Animate)](http://www.maefloresta.com/portal/) 一款可以创建 HTML5 动画的工具。
    - [Black Magic Fusion (Adobe After Effects)](https://www.blackmagicdesign.com) 一款先进的合成软件,广泛应用于视觉特效、广电影视设计以及 3D 动画设计等领域。
- **中国开源镜像**
  - [阿里云开源镜像站](http://mirrors.aliyun.com/)
  - [网易开源镜像站](http://mirrors.163.com/)
  - [搜狐开源镜像站](http://mirrors.sohu.com/)
  - [北京交通大学](http://mirror.bjtu.edu.cn/)
  - [兰州大学](http://mirror.lzu.edu.cn/)
  - [厦门大学](http://mirrors.xmu.edu.cn/)
  - [上海交通大学](http://ftp.sjtu.edu.cn/)
  - [清华大学](http://mirrors.tuna.tsinghua.edu.cn/)
  - [中国科学技术大学](http://mirrors.ustc.edu.cn/)
  - [东北大学](http://mirror.neu.edu.cn/)
  - [浙江大学](http://mirrors.zju.edu.cn/)
  - [东软信息学院](http://mirrors.neusoft.edu.cn/)
  - [校园网联合镜像站](https://mirrors.cernet.edu.cn)

## 🚪 传送门

◾ 💧 [钝悟的 IT 知识图谱](https://dunwu.github.io/waterdrop/) ◾ 🎯 [钝悟的博客](https://dunwu.github.io/blog/) ◾


================================================
FILE: codes/docker/docker-compose-demo/Dockerfile
================================================
FROM python:3.6-alpine
ADD . /code
WORKDIR /code
RUN pip install redis flask
CMD ["python", "app.py"]


================================================
FILE: codes/docker/docker-compose-demo/app.py
================================================
from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host='redis', port=6379)

@app.route('/')
def hello():
    count = redis.incr('hits')
    return 'Hello World! 该页面已被访问 {} 次。\n'.format(count)

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)


================================================
FILE: codes/docker/docker-compose-demo/docker-compose.yml
================================================
version: '3'
services:

  web:
    build: .
    ports:
      - "5000:5000"

  redis:
    image: "redis:alpine"


================================================
FILE: codes/docker/docker-compose-demo/run.sh
================================================
#!/usr/bin/env bash

set -x
docker-compose up


================================================
FILE: codes/expect/远程登录.sh
================================================
#!/usr/bin/expect -f

# -----------------------------------------------------------------------------------------------------
# expect 交互式脚本示例 - 自动远程登录,并在其他机器上创建一个文件
# @author Zhang Peng
# -----------------------------------------------------------------------------------------------------

# 设置变量
set USER "root"
set PWD "XXXXXX"
set HOST "127.0.0.2"
# 设置超时时间
set timeout 400

# 远程登录
spawn ssh -p 22 $USER@$HOST
expect {
  "yes/no" { send "yes\r"; exp_continue }
  "password:" { send "$PWD\r" }
}

# 在其他机器上创建
expect "#"
send "touch /home/demo.txt\r"
expect "#"
send "echo hello world >> /home/demo.txt\r"
expect "#"
# 退出
send "exit\r"


================================================
FILE: codes/linux/README.md
================================================
# CentOS 常规操作运维脚本集合

> **本项目脚本代码用于在 [CentOS](https://www.centos.org/) 机器上安装常用命令工具或开发软件。**

使用说明:

(1)下载脚本

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/download.sh | bash
```

(2)执行脚本

```shell
cd /tmp/dunwu-ops
./dunwu-ops.sh
```

(3)清除脚本

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/clear.sh | bash
```

本项目总结、收集 Linux 环境下运维常用到的脚本工具,大致分为三类:

- [系统运维脚本](sys)
- [服务、应用运维脚本](soft)
- [构建、编译项目脚本(目前支持 Java、Javascript 应用)](build)


================================================
FILE: codes/linux/build/Java应用运行脚本模板/lifecycle.sh
================================================
#!/usr/bin/env bash

# -----------------------------------------------------------------------------------------------------
# 应用终止脚本
# @author Zhang Peng
# -----------------------------------------------------------------------------------------------------


# ------------------------------------------------------------------------------ libs

SCRIPTS_DIR=$(cd `dirname $0`; pwd)

if [[ ! -x ${SCRIPTS_DIR}/utils.sh ]]; then
    logError "${SCRIPTS_DIR}/utils.sh not exists!"
    exit 1
fi
source ${SCRIPTS_DIR}/utils.sh


# ------------------------------------------------------------------------------ functions

stopServer() {
    if [[ ! $1 ]]; then
        logError "please input java app name"
        return ${ENV_FAILED}
    fi

    local appName=$1
    local pid=`jps | grep ${appName} | awk '{print $1}'`
    if [[ -n "${pid}" ]]; then
        kill -9 ${pid}
        if [[ $? -eq ${ENV_SUCCEED} ]]; then
            printInfo "stop ${appName} succeed"
            return ${ENV_SUCCEED}
        else
            logError "stop ${appName} failed"
            return ${ENV_FAILED}
        fi
    else
        printWarn "${appName} is not running"
        return ${ENV_SUCCEED}
    fi
}

startServer() {

    # >>>> validate params
    if [[ ! $1 ]] || [[ ! $2 ]] || [[ ! $3 ]] || [[ ! $4 ]]; then
        logError "you must input following params in order:"
        echo -e "${ENV_COLOR_B_RED}"
        echo "    (1)jarPath"
        echo "    (2)libPath"
        echo "    (3)confPath"
        echo "    (4)logPath"
        echo "    (5)appName    [optional]"
        echo "    (6)port       [optional]"
        echo "    (7)profile    [optional]"
        echo "    (8)debug      [optional]"
        echo -e "\nEg. startServer /usr/lib/dunwu/app.jar /usr/lib/dunwu/lib /usr/lib/dunwu/conf /var/log/dunwu dunwu 8888 prod off"
        echo -e "${ENV_COLOR_RESET}"
        return ${ENV_FAILED}
    fi

    local jarPath=$1
    local libPath=$2
    local confPath=$3
    local logPath=$4
    local appName=${5:-myapp}
    local port=${6:-8888}
    local profile=${7:-prod}
    local debug=${8:-off}

    # >>>> 1. check java app is started or not
    # >>>> 1.1. exit script if the app is started
    local pid=`jps | grep ${appName} | awk '{print $1}'`
    if [[ -n "${pid}" ]]; then
        printInfo "${appName} is started, PID: ${pid}"
        return ${ENV_SUCCEED}
    fi

    # >>>> 2. package options
    # GC OPTS
    local javaOptions="-server -Xms1g -Xmx2g -Xss256k"
    javaOptions="${javaOptions} -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:NewRatio=4"

    # GC LOG OPTS
    javaOptions="${javaOptions} -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps"
    javaOptions="${javaOptions} -verbose:gc -Xloggc:${logPath}/${appName}.gc.log"
    javaOptions="${javaOptions} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"

    # Heap Dump OPTS
    javaOptions="${javaOptions} -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError"
    javaOptions="${javaOptions} -XX:HeapDumpPath=${logPath}/${appName}.heapdump.hprof"

    # APP OPTS
    javaOptions="${javaOptions} -Dsun.net.inetaddr.ttl=60 -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8"
    if [[ ${profile} ]]; then
        javaOptions="${javaOptions} -Dspring.profiles.active=${profile}"
    fi

    # DEBUG OPTS
    if [[ "${debug}" == "on" ]]; then
        # JMX OPTS
        local ip=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d '/')
        local jmxPort=$(expr 10000 + ${port})
        javaOptions="${javaOptions} -Dcom.sun.management.jmxremote=true"
        javaOptions="${javaOptions} -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
        javaOptions="${javaOptions} -Djava.rmi.server.hostname=${ip} -Dcom.sun.management.jmxremote.port=${jmxPort}"

        # Remote Debug
        local debugPort=$(expr 20000 + ${port})
        javaOptions="${javaOptions} -Xdebug -Xnoagent -Djava.compiler=NONE"
        javaOptions="${javaOptions} -Xrunjdwp:transport=dt_socket,address=${debugPort},server=y,suspend=n"
    fi

    # CLASSPATH
    local appOptions="-classpath ${libPath}/* -Dlogging.config=file:${confPath}/logback.${profile}.xml"
    local springConfigFiles="classpath:/,classpath:/config/"
    local springConfigFiles="${springConfigFiles},file:${confPath}/,file:${confPath}/application.properties"
    appOptions="${appOptions} --spring.config.location=${springConfigFiles}"
    appOptions="${appOptions} --spring.cache.ehcache.config=file:${confPath}/config/ehcache.xml"
    if [[ ${port} ]]; then
        appOptions="${appOptions} --server.port=${port}"
    fi

    # >>>> 3. create log dir and console log file
    local consoleLogPath=${logPath}/${appName}.console.log
    mkdir -p ${logPath}
    if [[ ! -x ${consoleLogPath} ]]; then
        touch ${consoleLogPath}
    fi

    # >>>> 4. start java app
    # print bootstrap info
    printInfo "starting ${appName}"
    echo -e "${ENV_COLOR_B_GREEN}"
    echo -e "${ENV_COLOR_B_CYAN}\nBOOT PARAMS:${ENV_COLOR_B_GREEN}\n\n"
    echo "appName=${appName}"
    echo "jarPath=${jarPath}"
    echo "libPath=${libPath}"
    echo "confPath=${confPath}"
    echo "logPath=${logPath}"
    echo "port=${port}"
    echo "profile=${profile}"
    echo "debug=${debug}"
    echo -e "${ENV_COLOR_B_CYAN}\nEXEC CLI:${ENV_COLOR_B_GREEN}\n\n"
    echo "nohup java ${javaOptions} -jar ${jarPath} ${appOptions} >> ${consoleLogPath} 2>&1 &"
    echo -e "${ENV_COLOR_RESET}"

    # exec boot cli
    nohup java ${javaOptions} -jar ${jarPath} ${appOptions} >> ${consoleLogPath} 2>&1 &

    # >>>> 5. check java app is started or not
    local pid=`jps | grep ${appName} | awk '{print $1}'`
    if [[ -n "${pid}" ]]; then
        printInfo "start ${appName} succeed, PID: ${pid}"
        return ${ENV_SUCCEED}
    else
        logError "start ${appName} failed"
        return ${ENV_FAILED}
    fi
}


================================================
FILE: codes/linux/build/Java应用运行脚本模板/start.sh
================================================
#!/usr/bin/env bash

# -----------------------------------------------------------------------------------------------------
# myapp 启动脚本,用于【虚拟机环境】
# @author Zhang Peng
# -----------------------------------------------------------------------------------------------------


# ------------------------------------------------------------------------------ libs

SCRIPTS_DIR=$(dirname ${BASH_SOURCE[0]})
if [[ ! -x ${SCRIPTS_DIR}/lifecycle.sh ]]; then
    logError "${SCRIPTS_DIR}/lifecycle.sh not exists!"
    exit 1
fi
source ${SCRIPTS_DIR}/lifecycle.sh


# ------------------------------------------------------------------------------ main

APP_DIR=$(cd `dirname $0`/..; pwd)

export LANG="zh_CN.UTF-8"
APP=myapp
JAR_PATH=${APP_DIR}/myapp.jar
LIB_PATH=${APP_DIR}/lib
CONF_PATH=${APP_DIR}/config
LOG_DIR=/var/log/dunwu
PORT=8888
PROFILE=prod
DEBUG=off

declare -a serial
serial=(on off)
echo -n "是否启动 debug 模式(可选值:on|off):"
read DEBUG
if ! echo ${serial[@]} | grep -q ${DEBUG}; then
  echo "是否启动 debug 模式(可选值:on|off)"
  exit 1
fi

startServer ${JAR_PATH} ${LIB_PATH} ${CONF_PATH} ${LOG_DIR} ${APP} ${PORT} ${PROFILE} ${DEBUG}


================================================
FILE: codes/linux/build/Java应用运行脚本模板/stop.sh
================================================
#!/usr/bin/env bash

# -----------------------------------------------------------------------------------------------------
# 应用启动脚本
# @author Zhang Peng
# -----------------------------------------------------------------------------------------------------


# ------------------------------------------------------------------------------ libs

SCRIPTS_DIR=$(dirname ${BASH_SOURCE[0]})
if [[ ! -x ${SCRIPTS_DIR}/lifecycle.sh ]]; then
    logError "${SCRIPTS_DIR}/lifecycle.sh not exists!"
    exit 1
fi
source ${SCRIPTS_DIR}/lifecycle.sh


# ------------------------------------------------------------------------------ main

export LANG="zh_CN.UTF-8"
stopServer myapp


================================================
FILE: codes/linux/build/Java应用运行脚本模板/utils.sh
================================================
#!/usr/bin/env bash

# -----------------------------------------------------------------------------------------------------
# Shell Utils
# 使用此脚本,应该先 export ENV_LOG_PATH,指定日志路径;否则将使用默认日志路径 /var/log/shell.log
# @author Zhang Peng
# -----------------------------------------------------------------------------------------------------

# ------------------------------------------------------------------------------ env params

#  颜色状态
# Regular Color
export ENV_COLOR_BLACK="\033[0;30m"
export ENV_COLOR_RED="\033[0;31m"
export ENV_COLOR_GREEN="\033[0;32m"
export ENV_COLOR_YELLOW="\033[0;33m"
export ENV_COLOR_BLUE="\033[0;34m"
export ENV_COLOR_MAGENTA="\033[0;35m"
export ENV_COLOR_CYAN="\033[0;36m"
export ENV_COLOR_WHITE="\033[0;37m"
# Bold Color
export ENV_COLOR_B_BLACK="\033[1;30m"
export ENV_COLOR_B_RED="\033[1;31m"
export ENV_COLOR_B_GREEN="\033[1;32m"
export ENV_COLOR_B_YELLOW="\033[1;33m"
export ENV_COLOR_B_BLUE="\033[1;34m"
export ENV_COLOR_B_MAGENTA="\033[1;35m"
export ENV_COLOR_B_CYAN="\033[1;36m"
export ENV_COLOR_B_WHITE="\033[1;37m"
# Underline Color
export ENV_COLOR_U_BLACK="\033[4;30m"
export ENV_COLOR_U_RED="\033[4;31m"
export ENV_COLOR_U_GREEN="\033[4;32m"
export ENV_COLOR_U_YELLOW="\033[4;33m"
export ENV_COLOR_U_BLUE="\033[4;34m"
export ENV_COLOR_U_MAGENTA="\033[4;35m"
export ENV_COLOR_U_CYAN="\033[4;36m"
export ENV_COLOR_U_WHITE="\033[4;37m"
# Background Color
export ENV_COLOR_BG_BLACK="\033[40m"
export ENV_COLOR_BG_RED="\033[41m"
export ENV_COLOR_BG_GREEN="\033[42m"
export ENV_COLOR_BG_YELLOW="\033[43m"
export ENV_COLOR_BG_BLUE="\033[44m"
export ENV_COLOR_BG_MAGENTA="\033[45m"
export ENV_COLOR_BG_CYAN="\033[46m"
export ENV_COLOR_BG_WHITE="\033[47m"
# Reset Color
export ENV_COLOR_RESET="$(tput sgr0)"

# 常用状态值
export ENV_YES=0
export ENV_NO=1
export ENV_SUCCEED=0
export ENV_FAILED=1


# ------------------------------------------------------------------------------ functions

# 显示打印日志的时间
SHELL_LOG_TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
# 那个用户在操作
USER=$(whoami)
# 日志路径
LOG_PATH=${ENV_LOG_PATH:-/var/log/shell.log}
# 日志目录
LOG_DIR=${LOG_PATH%/*}

createLogFileIfNotExists() {
    if [[ ! -x "${LOG_PATH}" ]]; then
    mkdir -p "${LOG_DIR}"
    touch "${LOG_PATH}"
    fi
}

logInfo() {
    echo -e "${ENV_COLOR_B_GREEN}[INFO] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [INFO] [$0] $@" >> "${LOG_PATH}"
}

logWarn() {
    echo -e "${ENV_COLOR_B_YELLOW}[WARN] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [WARN] [$0] $@" >> "${LOG_PATH}"
}

logError() {
    echo -e "${ENV_COLOR_B_RED}[ERROR] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [ERROR] [$0] $@" >> "${LOG_PATH}"
}

printInfo() {
    echo -e "${ENV_COLOR_B_GREEN}[INFO] $@${ENV_COLOR_RESET}"
}

printWarn() {
    echo -e "${ENV_COLOR_B_YELLOW}[WARN] $@${ENV_COLOR_RESET}"
}

printError() {
    echo -e "${ENV_COLOR_B_RED}[ERROR] $@${ENV_COLOR_RESET}"
}

callAndLog () {
    $*
    if [[ $? -eq ${ENV_SUCCEED} ]]; then
        logInfo "$@"
        return ${ENV_SUCCEED}
    else
        logError "$@ EXECUTE ENV_FAILED"
        return ${ENV_FAILED}
    fi
}


================================================
FILE: codes/linux/build/README.md
================================================
# 构建、编译项目脚本

> 目前支持 Java、Javascript 应用


================================================
FILE: codes/linux/build/helper.sh
================================================
#!/usr/bin/env bash

# 打印UI页头信息
function printHeadInfo() {
	cat << EOF
***********************************************************************************
* 欢迎使用项目引导式发布脚本。
* 输入任意键进入脚本操作。
***********************************************************************************
EOF
}

# 打印UI页尾信息
function printFootInfo() {
	cat << EOF


***********************************************************************************
* 安装过程结束。
* 输入任意键进入脚本操作。
* 如果不想安装其他应用,输入 exit 回车或输入 <CTRL-C> 退出。
***********************************************************************************
EOF
}

# 检查文件是否存在,不存在则退出脚本
function checkFileExist() {
	if [ ! -f "$1" ]
	then
		echo "关键文件 $1 找不到,脚本执行结束"
		exit 1
	fi
}

# 检查文件夹是否存在,不存在则创建
function createFolderIfNotExist() {
	if [ ! -d "$1" ]; then
		mkdir -p "$1"
	fi
}

# 记录发布的版本信息
# 第一个参数为日志所在路径
# 第二个参数为应用名称
# 第三个参数为代码分支
# 第四个参数为运行环境
function saveVersionInfo() {
	if [ "$1" == "" ] || [ "$2" == "" ] || [ "$3" == "" ] || [ "$4" == "" ]; then
		echo "缺少参数,退出"
		exit 1
	fi

	VERSION_LOG_FILE=$1/$2-version.log
	rm -rf ${VERSION_LOG_FILE}
	touch ${VERSION_LOG_FILE}
	chmod 777 ${VERSION_LOG_FILE}

	echo -e "\n=================== $2 ===================" >> ${VERSION_LOG_FILE}
	echo "Branch is: $3" >> ${VERSION_LOG_FILE}
	echo "Profile is: $4" >> ${VERSION_LOG_FILE}
	echo "CommitID is : $(git log --pretty=oneline -1)" >> ${VERSION_LOG_FILE}
}


================================================
FILE: codes/linux/build/java-app-boot.sh
================================================
#!/usr/bin/env bash

#################################################################################
# JAVA 应用通用启动脚本
# @author: Zhang Peng
#################################################################################

# 检查脚本参数,如必要参数未传入,退出脚本。
function checkInput() {
	if [ "${app}" == "" ] || [ "${oper}" == "" ] || [ "${javaArgs}" == "" ] || [ "${classpathArgs}" == "" ] || [ "${bootstrapClass}" == "" ]; then
		echo "请输入脚本参数:app oper javaArgs classpathArgs bootstrapClass"
		echo "    app: 应用名。"
		echo "    oper: 运行环境(必填)。可选值:start|stop|restart"
		echo "    javaArgs: JVM 参数(必填)。"
		echo "    classpathArgs: classpath参数(必填)。"
		echo "    bootstrapClass: 启动类(必填)。"
		exit 0
	fi
}

# 检查文件夹是否存在,不存在则创建
function createFolderIfNotExist() {
	if [ ! -d "$1" ]; then
		mkdir -p "$1"
	fi
}

# 检查服务是否已经启动
pids=""
function checkStarted() {
	pids=`ps -ef | grep java | grep ${app} | awk '{print $2}'`
	if [ -n "${pids}" ]; then
		return 0
	else
		return 1
	fi
}

function main() {
	case "${oper}" in
		start)
			echo -n "starting server: "
			# 检查服务是否已经启动
			if checkStarted; then
				echo "ERROR: server already started!"
				echo "PID: ${pids}"
				exit 1
			fi

			args="${javaArgs} -classpath ${classpathArgs} ${bootstrapClass}"
			echo -e "statup params:\n ${args}"

			#启动服务
			touch ${LOG_DIR}/${app}-startup.log
			nohup java ${args} > ${LOG_DIR}/${app}-startup.log 2>&1 &
			# echo -e "执行参数:\n${args}"
			echo -e "\nthe server is started..."
		;;
		stop)
			echo -n "stopping server: "
			#dubbo提供优雅停机, 不能使用kill -9
			if checkStarted; then
				kill ${pids}
				echo -e "\nthe server is stopped..."
			else
				echo -e "\nno server to be stopped..."
			fi
		;;
		restart)
			$0 ${app} stop "${javaArgs}" "${classpathArgs}" "${bootstrapClass}"
			sleep 5
			$0 ${app} start "${javaArgs}" "${classpathArgs}" "${bootstrapClass}"
		;;
		*)
			echo "Invalid oper: ${oper}."
			exit 1
	esac

	exit 0
}

######################################## MAIN ########################################
# 设置环境变量
export LANG="zh_CN.UTF-8"

# 获取输入参数
app=`echo $1`
oper=`echo $2`
javaArgs=`echo $3`
classpathArgs=`echo $4`
bootstrapClass=`echo $5`
vars=$*
checkInput

# 设置全局常量
LOG_DIR=/home/zp/log
createFolderIfNotExist ${LOG_DIR}

# 执行 main 方法
main


================================================
FILE: codes/linux/build/java-app-release.sh
================================================
#!/usr/bin/env bash

#################################################################################
# JAVA 应用发布脚本
# @author: Zhang Peng
#################################################################################

# 检查脚本参数,如必要参数未传入,退出脚本。
checkInput() {
	if [ "${branch}" == "" ] || [ "${profile}" == "" ]; then
		echo "请输入脚本参数:branch profile"
		echo "    branch: git分支(必填)。如 feature/1.1.16, master"
		echo "    profile: 运行环境(必填)。可选值:development | test"
		echo "例:./java-app-release.sh feature/1.1.16 test"
		exit 0
	fi
}

# 检查文件是否存在,不存在则退出脚本
checkFileExist() {
	if [ ! -f "$1" ]
	then
		echo "关键文件 $1 找不到,脚本执行结束"
		exit 0
	fi
}

# 检查文件夹是否存在,不存在则创建
createFolderIfNotExist() {
	if [ ! -d "$1" ]; then
		mkdir -p "$1"
	fi
}

# 记录发布的版本信息
saveVersionInfo() {
	rm -rf ${VERSION_LOG_FILE}
	touch ${VERSION_LOG_FILE}
	chmod 777 ${VERSION_LOG_FILE}

	echo -e "\n=================== Version Info ===================" >> ${VERSION_LOG_FILE}
	echo "Branch is: ${branch}" >> ${VERSION_LOG_FILE}
	echo "Profile is: ${profile}" >> ${VERSION_LOG_FILE}
	echo "CommitID is : $(git log --pretty=oneline -1)" >> ${VERSION_LOG_FILE}
}

######################################## MAIN ########################################
# 设置环境变量
export LANG="zh_CN.UTF-8"

# 设置全局常量
LOG_DIR=/home/zp/log/
SCRIPT_DIR=$(cd "$(dirname "$0")";
pwd)
SOURCE_DIR=/home/zp/source/
APP_NAME=XXX
RESOURCES_DIR=/home/zp/source/${APP_NAME}/src/main/resources
UPDATE_CODE_SCRIPT_FILE=${SCRIPT_DIR}/update-code.sh
MAVEN_LOG_FILE=${LOG_DIR}/${APP_NAME}-maven.log
VERSION_LOG_FILE=${LOG_DIR/${APP_NAME}-version.log

# 0. 获取传入参数并检查
branch=`echo $1`
profile=`echo $2`
checkInput
checkFileExist ${UPDATE_CODE_SCRIPT_FILE}
createFolderIfNotExist ${LOG_DIR}
createFolderIfNotExist ${SOURCE_DIR}

echo ">>>>>>>>>>>>>> 1. 停止应用"
${SCRIPT_DIR}/java-app-run.sh ${profile} stop

echo ">>>>>>>>>>>>>> 2. 更新代码"
${UPDATE_CODE_SCRIPT_FILE} ${APP_NAME} ${branch} ${SOURCE_DIR}
execode=$?
if [ "${execode}" == "0" ]; then
	echo "更新代码成功"
else
	echo "更新代码失败"
	exit 1
fi

echo ">>>>>>>>>>>>>> 3. 替换配置"
# 有则加,无则过

echo ">>>>>>>>>>>>>> 4. 构建编译"
cd ${SOURCE_DIR}/ck-lion
mvn clean package -e -Dmaven.test.skip=true | tee ${MAVEN_LOG_FILE}
eexecode=$?
if [ "${execode}" == "0" ]; then
	echo "构建编译成功"
	echo "编译详情见:${MAVEN_LOG_FILE}"
else
	echo "构建编译失败"
	echo "编译详情见:${MAVEN_LOG_FILE}"
	exit 1
fi

echo ">>>>>>>>>>>>>> 5. 启动应用"
# 手动释放内存
echo 3 > /proc/sys/vm/drop_caches
${SCRIPT_DIR}/java-app-run.sh ${profile} start
execode=$?
if [ "${execode}" == "0" ]; then
	echo "启动应用成功"
else
	echo "启动应用失败"
	exit 1
fi

echo ">>>>>>>>>>>>>> 6. 记录发布的版本信息"
saveVersionInfo

echo ">>>>>>>>>>>>>> 发布应用结束"


================================================
FILE: codes/linux/build/java-app-run.sh
================================================
#!/usr/bin/env bash

#################################################################################
# JAVA 应用运行脚本
# @author: Zhang Peng
#################################################################################

# 检查脚本参数,如必要参数未传入,退出脚本。
function checkInput() {
	if [ "${profile}" == "" ] || [ "${oper}" == "" ]; then
		echo "请输入脚本参数:profile oper [debug]"
		echo "    profile: 运行环境(必填)。可选值:development|test"
		echo "    oper: 运行环境(必填)。可选值:start|stop|restart"
		echo "    debug: debug启动开关。默认不填为不启动。"
		exit 0
	fi
}

#检查文件是否存在,不存在则退出脚本
function checkFileExist() {
	if [ ! -f "$1" ]
	then
		echo "关键文件 $1 找不到,脚本执行结束"
		exit 0
	fi
}

# 封装启动参数,调用启动脚本
function main() {
	APP_NAME=ck-lion

	# JVM 参数
	JAVA_OPTS=" -Djava.awt.headless=true -Dfile.encoding=UTF8 -Djava.net.preferIPv4Stack=true -Ddubbo.shutdown.hook=true -Dspring.profiles.active=${profile} -Djava.security.egd=file:/dev/./urandom -Xms1024m -Xmx1024m -Xss2m "
	JAVA_DEBUG_OPTS=""
	if [ "$2" == "debug" ]; then
		JAVA_DEBUG_OPTS=" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=2236,server=y,suspend=n "
		shift
	fi
	javaArgs=" ${JAVA_OPTS} ${JAVA_DEBUG_OPTS} "

	# classpath 参数
	classpathArgs="${SERVER_ROOT}/WEB-INF/classes:${SERVER_ROOT}/WEB-INF/lib/*"

	# 启动类
	bootstrapClass="com.alibaba.dubbo.container.Main"

	${SCRIPT_DIR}/java-app-boot.sh ${APP_NAME} ${oper} "${javaArgs}" "${classpathArgs}" "${bootstrapClass}"
	execode=$?
	if [ "${execode}" == "0" ]; then
		echo "执行操作成功"
	else
		echo "执行操作失败"
		exit 1
	fi
}

######################################## MAIN ########################################
# 设置环境变量
export LANG="zh_CN.UTF-8"

# 设置全局常量
SCRIPT_DIR=$(cd "$(dirname "$0")";
pwd)
SOURCE_DIR=/home/zp/source/
APP_NAME=XXX
SERVER_ROOT=/home/zp/source/${APP_NAME}/target/

# 0. 获取传入参数并检查
profile=$1
oper=$2
debug=$3
checkInput

# 1. 执行操作
main


================================================
FILE: codes/linux/build/js-app-release.sh
================================================
#################################################################################
# 前端应用发布脚本
# 环境要求:Nvm、Node.js
#################################################################################

# 检查脚本参数,如必要参数未传入,退出脚本。
function checkInput() {
	if [ "${branch}" == "" ]; then
		echo "请输入脚本参数:branch"
		echo "    branch: git分支。如 feature/1.1.16, master"
		exit 1
	fi
}

# 脚本主方法
function main() {
	echo ">>>>>>>>>>>>>> 1. 更新代码"
	${SCRIPT_DIR}/update-code.sh ${APP} ${branch} ${SOURCE_DIR}
	execode=$?
	if [ "${execode}" == "0" ]; then
		echo "更新代码成功"
	else
		echo "更新代码失败"
		exit 1
	fi

	echo ">>>>>>>>>>>>>> 2. 替换配置"
	# 有的应用此处可能需要替换配置

	echo ">>>>>>>>>>>>>> 3. 构建编译"
	cd ${SOURCE_DIR}/${APP}
	source "${HOME}/.nvm/nvm.sh"
	nvm use 8.9
	npm install
	if [ "${profile}" == "develop" ] || [ "${profile}" == "test" ]; then
		npm start
	elif [ "${profile}" == "preview" ] || [ "${profile}" == "product" ]; then
		npm run build
	fi
	execode=$?
	if [ "${execode}" == "0" ]; then
		echo "构建编译成功"
	else
		echo "构建编译失败"
		exit 1
	fi

	echo ">>>>>>>>>>>>>> 4. 记录发布的版本信息"
	saveVersionInfo ${LOG_DIR} ${APP} ${branch} ${profile}

	echo ">>>>>>>>>>>>>> 发布应用结束"
}

######################################## MAIN ########################################
# 设置环境变量
export LANG="zh_CN.UTF-8"

# 设置全局常量
APP=blog
LOG_DIR=/home/zp/log
SOURCE_DIR=/home/zp/source
SCRIPT_DIR=$(cd "$(dirname "$0")";
pwd)

# 装载函数库
. ${SCRIPT_DIR}/helper.sh

# 获取传入参数并检查
branch=`echo $1`
profile=`echo $2`

checkInput
checkFileExist ${SCRIPT_DIR}/update-code.sh
createFolderIfNotExist ${SOURCE_DIR}

# 运行主方法
main


================================================
FILE: codes/linux/build/main.sh
================================================
#!/usr/bin/env bash

###################################################################################
# 项目发布脚本模板
# @author: Zhang Peng
###################################################################################

# 选择应用
function chooseAppName() {
	cat << EOF
请选择应用名(数字或关键字均可)。
可选值如下:
    [0] all (所有应用)
    [1] js-app
    [2] APP2
EOF

	while read app
	do
		case ${app} in
			0)
				app=all
				break ;;
			1)
				app=js-app
				break ;;
			2)
				app=APP2
				break ;;
			all | js-app | APP2)
				break ;;
			*) echo "无法识别 ${app}" ;;
		esac
	done
}

# 选择操作
function chooseOper() {
	cat << EOF
请选择想要执行的操作(数字或关键字均可)。
可选值如下:
    [1] start
    [2] restart
    [3] stop
EOF

	while read oper
	do
		case ${oper} in
			1)
				oper=start
				break ;;
			2)
				oper=restart
				break ;;
			3)
				oper=stop
				break ;;
			start | restart | stop)
				break ;;
			*) echo "无法识别 ${oper}" ;;
		esac
	done
}

# 选择代码分支
function chooseBranch() {
	cat << EOF
请输入 git 分支。
如:develop、master、feature/xxx
EOF

	read branch
	if [[ "${branch}" =~ ^ ( feature/ ) ( [^ \f\n\r\t\v]+ ) ]] || [ "${branch}" == "develop" ] || [ "${branch}" == "master" ]; then
		echo "输入了 ${branch}"
	else
		echo "无法识别 ${branch}"
		chooseBranch
	fi
}

# 选择运行环境
function chooseProfile() {
	cat << EOF
请选择运行环境(数字或关键字均可)。
可选值:
    [1] develop (开发环境)
    [2] test (测试环境)
    [3] preview (预发布环境)
    [4] product (生产环境)
EOF

	while read profile
	do
		case ${profile} in
			1)
				profile=develop
				break ;;
			2)
				profile=test
				break ;;
			3)
				profile=preview
				break ;;
			4)
				profile=product
				break ;;
			develop | test | preview | product)
				break ;;
			*) echo "无法识别 ${profile}" ;;
		esac
	done
}

# 确认选择
function confirmChoice() {

	cat << EOF
===================================================
请确认您的选择:Y/N
    app: ${app}
    oper: ${oper}
    branch: ${branch}
    profile: ${profile}
===================================================
EOF

	while read confirm
	do
		case ${confirm} in
			y | Y)
				echo -e "\n\n>>>>>>>>>>>>>> 开始发布应用"
				break ;;
			n | N)
				echo -e "重新输入发布参数\n"
				inputParams ;;
			*)
				echo "无法识别 ${confirm}" ;;
		esac
	done
}

# 引导式发布应用
function releaseApp() {
	# 输入执行参数
	app=""
	branch=""
	profile=""
	chooseAppName
	chooseOper
	if [ "${oper}" == "stop" ]; then
		confirmChoice
		if [ "${app}" == "all" ]; then
			${SCRIPT_DIR}/${app}-run.sh stop ${profile}
		else
			${SCRIPT_DIR}/${app}-run.sh stop ${profile}
		fi
	else
		chooseBranch
		chooseProfile
		confirmChoice
		if [ "${app}" == "all" ]; then
			${SCRIPT_DIR}/js-app-release.sh ${branch} ${profile}
		else
			${SCRIPT_DIR}/${app}-release.sh ${branch} ${profile}
		fi
	fi

}

# 脚本主方法
function main() {

	printHeadInfo
	while read sign
	do
		case ${sign} in
			exit)
				echo "主动退出脚本"
				exit 0 ;;
			*)
				releaseApp ;;
		esac

		# 装载函数库
		printFootInfo
	done
}

######################################## MAIN ########################################
# 设置环境变量
export LANG="zh_CN.UTF-8"

# 设置全局常量
SCRIPT_DIR=$(cd "$(dirname "$0")";
pwd)
SOURCE_DIR=/home/zp/source/

# 装载函数库
. ${SCRIPT_DIR}/helper.sh

# 检查必要文件或文件夹是否存在
checkFileExist ${SCRIPT_DIR}/helper.sh
createFolderIfNotExist ${SOURCE_DIR}

# 运行主方法
main


================================================
FILE: codes/linux/build/spring-boot-run.sh
================================================
#!/usr/bin/env bash

##############################################################################
# console color
BLACK="\033[1;30m"
RED="\033[1;31m"
GREEN="\033[1;32m"
YELLOW="\033[1;33m"
BLUE="\033[1;34m"
PURPLE="\033[1;35m"
CYAN="\033[1;36m"
RESET="$(tput sgr0)"
##############################################################################

JAVA_OPTS=""
APP_OPTS=""
packageJavaOpts() {

	# GC OPTS
	JAVA_OPTS="${JAVA_OPTS} -server -Xms8g -Xmx16g -Xss512k"
	JAVA_OPTS="${JAVA_OPTS} -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy -XX:MaxGCPauseMillis=150"
	JAVA_OPTS="${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom"

	# DEBUG OPTS
	if [[ ${debug} == "on" ]]; then

		# Remote Debug
		JAVA_OPTS="${JAVA_OPTS} -Xdebug -Xnoagent -Djava.compiler=NONE"
		JAVA_OPTS="${JAVA_OPTS} -Xrunjdwp:transport=dt_socket,address=28889,server=y,suspend=n"

		# GC LOG
		JAVA_OPTS="${JAVA_OPTS} -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps"
		JAVA_OPTS="${JAVA_OPTS} -verbose:gc -Xloggc:${LOG_PATH}/${APP_NAME}.gc.log"
		JAVA_OPTS="${JAVA_OPTS} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"

		# Heap Dump
		JAVA_OPTS="${JAVA_OPTS} -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError"
		JAVA_OPTS="${JAVA_OPTS} -XX:HeapDumpPath=${LOG_PATH}/${APP_NAME}.heapdump.hprof"

		# JMX OPTS
		IP=`ip addr | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | cut -d/ -f1`
		JAVA_OPTS="${JAVA_OPTS} -Dcom.sun.management.jmxremote=true"
		JAVA_OPTS="${JAVA_OPTS} -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
		JAVA_OPTS="${JAVA_OPTS} -Djava.rmi.server.hostname=${IP} -Dcom.sun.management.jmxremote.port=18889"
	fi

	# APP OPTS
	JAVA_OPTS="${JAVA_OPTS} -Dsun.net.inetaddr.ttl=60 -Djava.net.preferIPv4Stack=true"
	JAVA_OPTS="${JAVA_OPTS} -Dspring.profiles.active=${profile} -Dfile.encoding=UTF-8"

	# CLASSPATH
	APP_OPTS=" -classpath lib/* -Dlogging.config=file:./config/logback.dev.xml --spring.config.location=classpath:/,classpath:/config/,file:./,file:./config/"
}

# 检查服务是否已经启动
pid=""
checkStarted() {
	pid=`ps -ef | grep java | grep ${APP_NAME} | awk '{print $2}'`
	if [[ -n "${pid}" ]]; then
		return 0
	else
		return 1
	fi
}

main() {
	case "${oper}" in
		start)
			startServer
		;;
		stop)
			stopServer
		;;
		restart)
			stopServer
			sleep 5
			startServer
		;;
		*)
			echo "Invalid oper: ${oper}."
			exit 1
	esac

	exit 0
}

stopServer() {
	echo -n "stopping server: "
	if checkStarted; then
		kill -9 ${pid}
		printf "${GREEN}\n${APP_NAME} is stopped.${RESET}\n"
	else
		printf "${RED}\n${APP_NAME} fail to stop.${RESET}\n"
	fi
}

startServer() {
	printf "${BLUE}starting ${APP_NAME}...${RESET}\n"
	if checkStarted; then
		printf "${YELLOW}[WARN] ${APP_NAME} already started!${RESET}\n"
		printf "PID: ${pid}\n"
		exit 1
	fi

	packageJavaOpts
	printf "${CYAN}JVM OPTS:\n ${JAVA_OPTS}${RESET}\n"
	if [[ ! -f "${LOG_PATH}/start.out" ]]; then
		touch "${LOG_PATH}/start.out"
	fi
	nohup java ${JAVA_OPTS} -jar ${ROOT_DIR}/../spring-boot-app.jar ${APP_OPTS} >> ${LOG_PATH}/start.out 2>&1 &
	printf "${GREEN}\n${APP_NAME} is started.${RESET}\n"
}

######################################## MAIN ########################################
# 设置环境变量
export LANG="zh_CN.UTF-8"
ROOT_DIR=$(pwd)

APP_NAME=spring-boot-app
LOG_PATH=${ROOT_DIR}/../logs
mkdir -p ${LOG_PATH}

declare -a serial
serial=( start stop restart )
echo -n "请选择操作(可选值:start|stop|restart):"
read oper
if ! echo "${serial[@]}" | grep -q ${oper}; then
	echo "请选择正确操作(可选值:start|stop|restart)"
	exit 1
fi

if [[ ${oper} == "start" ]] || [[ "${oper}" == "restart" ]]; then
	declare -a serial2
	serial2=( prod dev test )
	echo -n "选择 profile(可选值:prod|dev|test):"
	read profile
	if ! echo "${serial2[@]}" | grep -q ${profile}; then
		echo "请选择正确 profile(可选值:prod|dev|test)"
		exit 1
	fi

	declare -a serial3
	serial3=( on off )
	echo -n "是否启动 debug 模式(可选值:on|off):"
	read debug
	if ! echo "${serial3[@]}" | grep -q ${debug}; then
		echo "是否启动 debug 模式(可选值:on|off)"
		exit 1
	fi
fi

main


================================================
FILE: codes/linux/build/update-code.sh
================================================
#!/usr/bin/env bash

###################################################################################
# 更新代码脚本
# 只有退出码(exit code)为 0 ,表示脚本执行成功。
# @author: Zhang Peng
###################################################################################

# 检查脚本参数,如必要参数未传入,退出脚本。
checkInput() {
	if [ "${repository}" == "" ] || [ "${branch}" == "" ]; then
		echo "请输入脚本参数:repository branch [source] [target]"
		echo "    repository: git 仓储(必填)。"
		echo "    branch: git 分支(必填)。如 master/develop"
		echo "    source: 代码存放目录。默认为/home/zp/source。"
		echo "    target: 代码存放目录。默认为脚本所在目录。"
		exit 1
	fi
}

# 检查文件夹是否存在,不存在则创建
function createFolderIfNotExist() {
	if [ ! -d "$1" ]; then
		mkdir -p "$1"
	fi
}

# 判断 git 版本库是否存在。根据实际结果修改 ${gitok} 值。
gitok=false
function isGitExist() {
	cd ${SOURCE_DIR}
	if [ -d "${SOURCE_DIR}/${repository}/${target}" ]; then
		cd ${SOURCE_DIR}/${repository}/${target}
		#(1)删除git状态零时文件
		if [ -f "gitstatus.tmp" ]; then
			rm -rf gitstatus.tmp
		fi

		#(2) 判断是否存在.git目录
		if [ -d "./.git" ]; then
			#(3) 判断git是否可用
			git status &> gitstatus.tmp
			grep -iwq 'not a git repository' gitstatus.tmp && gitok=false || gitok=true
		fi

		#返回到主目录
		cd ${SOURCE_DIR}
	fi
}

# 如果 git 版本库存在(根据 ${gitok} 值),执行 fetch 操作;反之,执行 clone 操作。
function doFetchOrClone() {
	if ${gitok}; then
		cd ${SOURCE_DIR}/${repository}/${target}
		git reset --hard
		git clean -ffdx
		git fetch
		echo "git fetch ${repository} remote repository 到本地成功"
	else
		#删除所有内容,便于重新进行git clone
		rm -rf ${repository}
		git clone --no-checkout git@github.com:${GITHUB_ACCOUNT}/${repository}.git ${SOURCE_DIR}/${repository}/${target}
		echo "git clone ${repository} remote repository 到本地成功"
		cd ${SOURCE_DIR}/${repository}/${target}
	fi
}

# 切换到 ${branch} 分支
function doCheckout() {
	echo "检出 ${repository} ${branch} 分支代码"
	isRemoteBranch=false
	gitRemoteBranch=`git branch -r`
	echo -e "$gitRemoteBranch" | grep -iwq ${branch} && isRemoteBranch=true || isRemoteBranch=false
	if ${isRemoteBranch}; then
		echo "找到 ${branch} 分支。"
		git checkout -f 'origin/'${branch}
	else
		echo "未找到 ${branch} 分支!"
		exit 2
	fi
	echo "更新子模块代码"
	git submodule update --init --recursive --force
}

######################################## MAIN ########################################
export LANG="zh_CN.UTF-8"

# 0. 检查传入的参数
repository=`echo $1`
branch=`echo $2`
source=`echo $3`
target=`echo $4`
checkInput

# 设置全局常量
GITHUB_ACCOUNT=dunwu
SOURCE_DIR=/home/xyz/source
if [ "${source}" != "" ]; then
	SOURCE_DIR=${source}
fi
createFolderIfNotExist ${SOURCE_DIR}

# 1. 判断本地是否已存在 Git 仓库
isGitExist

# 2. 如果本地已有代码,执行 fetch;反之,从远程 clone
doFetchOrClone

# 3. 切换到指定分支
doCheckout

# 4. 分配权限
chmod -R 777 ${SOURCE_DIR}

exit 0


================================================
FILE: codes/linux/conf/etc/sysctl.conf
================================================
###################################################################################
# /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


================================================
FILE: codes/linux/download.sh
================================================
#!/usr/bin/env bash

# ---------------------------------------------------------------------------------
# 控制台颜色
BLACK="\033[1;30m"
RED="\033[1;31m"
GREEN="\033[1;32m"
YELLOW="\033[1;33m"
BLUE="\033[1;34m"
PURPLE="\033[1;35m"
CYAN="\033[1;36m"
RESET="$(tput sgr0)"
# ---------------------------------------------------------------------------------

printf "${BLUE}\n"
cat << EOF
###################################################################################
# linux-tutorial 运维脚本工具集下载脚本
# 下载 https://github.com/dunwu/linux-tutorial 中的所有脚本到当前服务器的
# /home/scripts/linux-tutorial 目录下
# @system: 适用于 CentOS
# @author: Zhang Peng
# See: https://github.com/dunwu/linux-tutorial
###################################################################################
EOF
printf "${RESET}\n"

root=/home/scripts/linux-tutorial
printf "\n${GREEN}>>>>>>>> Download linux-tutorial to ${root} begin.${RESET}\n"
command -v yum > /dev/null 2>&1 || {
	printf "\n${RED}Not detected yum.${RESET}";
	exit 1;
}

command -v git > /dev/null 2>&1 || {
	printf "\n${YELLOW}Not detected git. Install git.${RESET}\n";
	yum install -y git;
}

if [[ -d ${root} ]]; then
	cd ${root}
	git pull
else
	mkdir -p ${root}
	git clone https://gitee.com/turnon/linux-tutorial.git ${root}
fi
chmod +x -R ${root}
printf "\n${GREEN}<<<<<<<< Download linux-tutorial to ${root} end.${RESET}\n"


================================================
FILE: codes/linux/dunwu-ops.sh
================================================
#!/usr/bin/env bash

# ------------------------------------------------------------------------------
# CentOS 常用软件一键安装脚本
# @author Zhang Peng
# ------------------------------------------------------------------------------

# ------------------------------------------------------------------------------ env

# Regular Color
export ENV_COLOR_BLACK="\033[0;30m"
export ENV_COLOR_RED="\033[0;31m"
export ENV_COLOR_GREEN="\033[0;32m"
export ENV_COLOR_YELLOW="\033[0;33m"
export ENV_COLOR_BLUE="\033[0;34m"
export ENV_COLOR_MAGENTA="\033[0;35m"
export ENV_COLOR_CYAN="\033[0;36m"
export ENV_COLOR_WHITE="\033[0;37m"
# Bold Color
export ENV_COLOR_B_BLACK="\033[1;30m"
export ENV_COLOR_B_RED="\033[1;31m"
export ENV_COLOR_B_GREEN="\033[1;32m"
export ENV_COLOR_B_YELLOW="\033[1;33m"
export ENV_COLOR_B_BLUE="\033[1;34m"
export ENV_COLOR_B_MAGENTA="\033[1;35m"
export ENV_COLOR_B_CYAN="\033[1;36m"
export ENV_COLOR_B_WHITE="\033[1;37m"
# Underline Color
export ENV_COLOR_U_BLACK="\033[4;30m"
export ENV_COLOR_U_RED="\033[4;31m"
export ENV_COLOR_U_GREEN="\033[4;32m"
export ENV_COLOR_U_YELLOW="\033[4;33m"
export ENV_COLOR_U_BLUE="\033[4;34m"
export ENV_COLOR_U_MAGENTA="\033[4;35m"
export ENV_COLOR_U_CYAN="\033[4;36m"
export ENV_COLOR_U_WHITE="\033[4;37m"
# Background Color
export ENV_COLOR_BG_BLACK="\033[40m"
export ENV_COLOR_BG_RED="\033[41m"
export ENV_COLOR_BG_GREEN="\033[42m"
export ENV_COLOR_BG_YELLOW="\033[43m"
export ENV_COLOR_BG_BLUE="\033[44m"
export ENV_COLOR_BG_MAGENTA="\033[45m"
export ENV_COLOR_BG_CYAN="\033[46m"
export ENV_COLOR_BG_WHITE="\033[47m"
# Reset Color
export ENV_COLOR_RESET="$(tput sgr0)"

# status
export ENV_YES=0
export ENV_NO=1
export ENV_SUCCEED=0
export ENV_FAILED=1


# ------------------------------------------------------------------------------ functions

# 显示打印日志的时间
SHELL_LOG_TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
# 那个用户在操作
USER=$(whoami)
# 日志路径
LOG_PATH=${ENV_LOG_PATH:-/var/log/shell.log}
# 日志目录
LOG_DIR=${LOG_PATH%/*}

createLogFileIfNotExists() {
    if [[ ! -x "${LOG_PATH}" ]]; then
    mkdir -p "${LOG_DIR}"
    touch "${LOG_PATH}"
    fi
}

redOutput() {
    echo -e "${ENV_COLOR_RED} $@${ENV_COLOR_RESET}"
}
greenOutput() {
    echo -e "${ENV_COLOR_B_GREEN} $@${ENV_COLOR_RESET}"
}
yellowOutput() {
    echo -e "${ENV_COLOR_YELLOW} $@${ENV_COLOR_RESET}"
}
blueOutput() {
    echo -e "${ENV_COLOR_BLUE} $@${ENV_COLOR_RESET}"
}
magentaOutput() {
    echo -e "${ENV_COLOR_MAGENTA} $@${ENV_COLOR_RESET}"
}
cyanOutput() {
    echo -e "${ENV_COLOR_CYAN} $@${ENV_COLOR_RESET}"
}
whiteOutput() {
    echo -e "${ENV_COLOR_WHITE} $@${ENV_COLOR_RESET}"
}

logInfo() {
    echo -e "${ENV_COLOR_B_GREEN}[INFO] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [INFO] [$0] $@" >> "${LOG_PATH}"
}
logWarn() {
    echo -e "${ENV_COLOR_B_YELLOW}[WARN] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [WARN] [$0] $@" >> "${LOG_PATH}"
}
logError() {
    echo -e "${ENV_COLOR_B_RED}[ERROR] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [ERROR] [$0] $@" >> "${LOG_PATH}"
}

printInfo() {
    echo -e "${ENV_COLOR_B_GREEN}[INFO] $@${ENV_COLOR_RESET}"
}
printWarn() {
    echo -e "${ENV_COLOR_B_YELLOW}[WARN] $@${ENV_COLOR_RESET}"
}
printError() {
    echo -e "${ENV_COLOR_B_RED}[ERROR] $@${ENV_COLOR_RESET}"
}

callAndLog () {
    $*
    if [[ $? -eq ${ENV_SUCCEED} ]]; then
        logInfo "$@"
        return ${ENV_SUCCEED}
    else
        logError "$@ EXECUTE FAILED"
        return ${ENV_FAILED}
    fi
}

# ------------------------------------------------------------------------------ functions

# 打印头部信息
printHeadInfo() {
printf "${C_B_BLUE}\n"
cat << EOF
###################################################################################
# 欢迎使用 Dunwu Shell 运维脚本
# 适用于 Linux CentOS 环境
# @author: Zhang Peng
###################################################################################
EOF
printf "${C_RESET}\n"
}

# 打印尾部信息
printFootInfo() {
printf "${C_B_BLUE}\n"
cat << EOF
###################################################################################
# 脚本执行结束,感谢使用!
###################################################################################
EOF
printf "${C_RESET}\n"
}

# 检查操作系统环境
checkOsVersion() {
	if (($1 == 1)); then
		platform=`uname -i`
		if [[ ${platform} != "x86_64" ]]; then
			logError "脚本仅支持 64 位操作系统!"
			exit 1
		fi

		version=`cat /etc/redhat-release | awk '{print substr($4,1,1)}'`
		if [[ ${version} != 7 ]]; then
			logError "脚本仅支持 CentOS 7!"
			exit 1
		fi
	fi
}

menus=( "配置系统" "安装软件" "退出" )
selectAndExecTask() {
	printHeadInfo
	PS3="请输入命令编号:"
	select item in "${menus[@]}"
	do
	case ${item} in
		"配置系统")
			./dunwu-sys.sh
			selectAndExecTask ;;
		"安装软件")
			./dunwu-soft.sh
			selectAndExecTask ;;
		"退出")
			printFootInfo
			exit 0 ;;
		*)
			logWarn "输入项不支持!"
			selectAndExecTask ;;
	esac
	break
	done
}


# ------------------------------------------------------------------------------ main

checkOsVersion 1
selectAndExecTask


================================================
FILE: codes/linux/dunwu-soft.sh
================================================
#!/usr/bin/env bash

# ------------------------------------------------------------------------------
# CentOS 常用软件一键安装脚本
# @author Zhang Peng
# ------------------------------------------------------------------------------

# ------------------------------------------------------------------------------ env

# Regular Color
export ENV_COLOR_BLACK="\033[0;30m"
export ENV_COLOR_RED="\033[0;31m"
export ENV_COLOR_GREEN="\033[0;32m"
export ENV_COLOR_YELLOW="\033[0;33m"
export ENV_COLOR_BLUE="\033[0;34m"
export ENV_COLOR_MAGENTA="\033[0;35m"
export ENV_COLOR_CYAN="\033[0;36m"
export ENV_COLOR_WHITE="\033[0;37m"
# Bold Color
export ENV_COLOR_B_BLACK="\033[1;30m"
export ENV_COLOR_B_RED="\033[1;31m"
export ENV_COLOR_B_GREEN="\033[1;32m"
export ENV_COLOR_B_YELLOW="\033[1;33m"
export ENV_COLOR_B_BLUE="\033[1;34m"
export ENV_COLOR_B_MAGENTA="\033[1;35m"
export ENV_COLOR_B_CYAN="\033[1;36m"
export ENV_COLOR_B_WHITE="\033[1;37m"
# Underline Color
export ENV_COLOR_U_BLACK="\033[4;30m"
export ENV_COLOR_U_RED="\033[4;31m"
export ENV_COLOR_U_GREEN="\033[4;32m"
export ENV_COLOR_U_YELLOW="\033[4;33m"
export ENV_COLOR_U_BLUE="\033[4;34m"
export ENV_COLOR_U_MAGENTA="\033[4;35m"
export ENV_COLOR_U_CYAN="\033[4;36m"
export ENV_COLOR_U_WHITE="\033[4;37m"
# Background Color
export ENV_COLOR_BG_BLACK="\033[40m"
export ENV_COLOR_BG_RED="\033[41m"
export ENV_COLOR_BG_GREEN="\033[42m"
export ENV_COLOR_BG_YELLOW="\033[43m"
export ENV_COLOR_BG_BLUE="\033[44m"
export ENV_COLOR_BG_MAGENTA="\033[45m"
export ENV_COLOR_BG_CYAN="\033[46m"
export ENV_COLOR_BG_WHITE="\033[47m"
# Reset Color
export ENV_COLOR_RESET="$(tput sgr0)"

# status
export ENV_YES=0
export ENV_NO=1
export ENV_SUCCEED=0
export ENV_FAILED=1


# ------------------------------------------------------------------------------ functions

# 显示打印日志的时间
SHELL_LOG_TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
# 那个用户在操作
USER=$(whoami)
# 日志路径
LOG_PATH=${ENV_LOG_PATH:-/var/log/shell.log}
# 日志目录
LOG_DIR=${LOG_PATH%/*}

createLogFileIfNotExists() {
    if [[ ! -x "${LOG_PATH}" ]]; then
    mkdir -p "${LOG_DIR}"
    touch "${LOG_PATH}"
    fi
}

redOutput() {
    echo -e "${ENV_COLOR_RED} $@${ENV_COLOR_RESET}"
}
greenOutput() {
    echo -e "${ENV_COLOR_B_GREEN} $@${ENV_COLOR_RESET}"
}
yellowOutput() {
    echo -e "${ENV_COLOR_YELLOW} $@${ENV_COLOR_RESET}"
}
blueOutput() {
    echo -e "${ENV_COLOR_BLUE} $@${ENV_COLOR_RESET}"
}
magentaOutput() {
    echo -e "${ENV_COLOR_MAGENTA} $@${ENV_COLOR_RESET}"
}
cyanOutput() {
    echo -e "${ENV_COLOR_CYAN} $@${ENV_COLOR_RESET}"
}
whiteOutput() {
    echo -e "${ENV_COLOR_WHITE} $@${ENV_COLOR_RESET}"
}

logInfo() {
    echo -e "${ENV_COLOR_B_GREEN}[INFO] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [INFO] [$0] $@" >> "${LOG_PATH}"
}
logWarn() {
    echo -e "${ENV_COLOR_B_YELLOW}[WARN] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [WARN] [$0] $@" >> "${LOG_PATH}"
}
logError() {
    echo -e "${ENV_COLOR_B_RED}[ERROR] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [ERROR] [$0] $@" >> "${LOG_PATH}"
}

printInfo() {
    echo -e "${ENV_COLOR_B_GREEN}[INFO] $@${ENV_COLOR_RESET}"
}
printWarn() {
    echo -e "${ENV_COLOR_B_YELLOW}[WARN] $@${ENV_COLOR_RESET}"
}
printError() {
    echo -e "${ENV_COLOR_B_RED}[ERROR] $@${ENV_COLOR_RESET}"
}

callAndLog () {
    $*
    if [[ $? -eq ${ENV_SUCCEED} ]]; then
        logInfo "$@"
        return ${ENV_SUCCEED}
    else
        logError "$@ EXECUTE FAILED"
        return ${ENV_FAILED}
    fi
}

# ------------------------------------------------------------------------------ functions
# 打印头部信息
printHeadInfo() {
printf "${C_B_BLUE}\n"
cat << EOF
###################################################################################
# 欢迎使用 CentOS 常用软件一键安装脚本
# 适用于 Linux CentOS 环境
# @author: Zhang Peng
###################################################################################
EOF
printf "${C_RESET}\n"
}

# print menu
printMenu() {
	printf "${C_B_MAGENTA}"
	menus=( docker fastdfs gitlab jdk8 jenkins kafka maven mongodb mysql nacos nexus nginx nodejs redis rocketmq tomcat8 zookeeper zsh exit )
	for i in "${!menus[@]}"; do
		index=`expr ${i} + 1`
		val=`expr ${index} % 2`
		printf "[%02d] %-20s" "${index}" "${menus[$i]}"
		if [[ ${val} -eq 0 ]]; then
			printf "\n"
		fi
	done

	printf "\n\n${C_B_BLUE}请选择需要安装的软件:${C_RESET}"
}

# exec shell to install soft
main() {
	printMenu
	read -t 30 index
	if [[ -n ${index} ]]; then
		no=`expr ${index} - 1`
		len=${#menus[*]}
		if [[ ${index} -gt ${len} ]]; then
			logWarn "输入项不支持!"
			exit 1
		fi
		key=${menus[$no]}
		if [[ ${key} == 'exit' ]]; then
			logInfo "退出软件安装脚本。"
			exit 0
		fi
		sh soft/${key}-install.sh
		printf "\n"
		main
	else
		logWarn "输入项不支持!"
		exit 1
	fi
}

# ------------------------------------------------------------------------------ main

printHeadInfo
main


================================================
FILE: codes/linux/dunwu-sys.sh
================================================
#!/usr/bin/env bash

# ------------------------------------------------------------------------------
# CentOS 环境初始化脚本
# @author Zhang Peng
# ------------------------------------------------------------------------------

# ------------------------------------------------------------------------------ env

# Regular Color
export ENV_COLOR_BLACK="\033[0;30m"
export ENV_COLOR_RED="\033[0;31m"
export ENV_COLOR_GREEN="\033[0;32m"
export ENV_COLOR_YELLOW="\033[0;33m"
export ENV_COLOR_BLUE="\033[0;34m"
export ENV_COLOR_MAGENTA="\033[0;35m"
export ENV_COLOR_CYAN="\033[0;36m"
export ENV_COLOR_WHITE="\033[0;37m"
# Bold Color
export ENV_COLOR_B_BLACK="\033[1;30m"
export ENV_COLOR_B_RED="\033[1;31m"
export ENV_COLOR_B_GREEN="\033[1;32m"
export ENV_COLOR_B_YELLOW="\033[1;33m"
export ENV_COLOR_B_BLUE="\033[1;34m"
export ENV_COLOR_B_MAGENTA="\033[1;35m"
export ENV_COLOR_B_CYAN="\033[1;36m"
export ENV_COLOR_B_WHITE="\033[1;37m"
# Underline Color
export ENV_COLOR_U_BLACK="\033[4;30m"
export ENV_COLOR_U_RED="\033[4;31m"
export ENV_COLOR_U_GREEN="\033[4;32m"
export ENV_COLOR_U_YELLOW="\033[4;33m"
export ENV_COLOR_U_BLUE="\033[4;34m"
export ENV_COLOR_U_MAGENTA="\033[4;35m"
export ENV_COLOR_U_CYAN="\033[4;36m"
export ENV_COLOR_U_WHITE="\033[4;37m"
# Background Color
export ENV_COLOR_BG_BLACK="\033[40m"
export ENV_COLOR_BG_RED="\033[41m"
export ENV_COLOR_BG_GREEN="\033[42m"
export ENV_COLOR_BG_YELLOW="\033[43m"
export ENV_COLOR_BG_BLUE="\033[44m"
export ENV_COLOR_BG_MAGENTA="\033[45m"
export ENV_COLOR_BG_CYAN="\033[46m"
export ENV_COLOR_BG_WHITE="\033[47m"
# Reset Color
export ENV_COLOR_RESET="$(tput sgr0)"

# status
export ENV_YES=0
export ENV_NO=1
export ENV_SUCCEED=0
export ENV_FAILED=1


# ------------------------------------------------------------------------------ functions

# 显示打印日志的时间
SHELL_LOG_TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
# 那个用户在操作
USER=$(whoami)
# 日志路径
LOG_PATH=${ENV_LOG_PATH:-/var/log/shell.log}
# 日志目录
LOG_DIR=${LOG_PATH%/*}

createLogFileIfNotExists() {
    if [[ ! -x "${LOG_PATH}" ]]; then
    mkdir -p "${LOG_DIR}"
    touch "${LOG_PATH}"
    fi
}

redOutput() {
    echo -e "${ENV_COLOR_RED} $@${ENV_COLOR_RESET}"
}
greenOutput() {
    echo -e "${ENV_COLOR_B_GREEN} $@${ENV_COLOR_RESET}"
}
yellowOutput() {
    echo -e "${ENV_COLOR_YELLOW} $@${ENV_COLOR_RESET}"
}
blueOutput() {
    echo -e "${ENV_COLOR_BLUE} $@${ENV_COLOR_RESET}"
}
magentaOutput() {
    echo -e "${ENV_COLOR_MAGENTA} $@${ENV_COLOR_RESET}"
}
cyanOutput() {
    echo -e "${ENV_COLOR_CYAN} $@${ENV_COLOR_RESET}"
}
whiteOutput() {
    echo -e "${ENV_COLOR_WHITE} $@${ENV_COLOR_RESET}"
}

logInfo() {
    echo -e "${ENV_COLOR_B_GREEN}[INFO] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [INFO] [$0] $@" >> "${LOG_PATH}"
}
logWarn() {
    echo -e "${ENV_COLOR_B_YELLOW}[WARN] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [WARN] [$0] $@" >> "${LOG_PATH}"
}
logError() {
    echo -e "${ENV_COLOR_B_RED}[ERROR] $@${ENV_COLOR_RESET}"
    createLogFileIfNotExists
    echo "[${SHELL_LOG_TIMESTAMP}] [${USER}] [ERROR] [$0] $@" >> "${LOG_PATH}"
}

printInfo() {
    echo -e "${ENV_COLOR_B_GREEN}[INFO] $@${ENV_COLOR_RESET}"
}
printWarn() {
    echo -e "${ENV_COLOR_B_YELLOW}[WARN] $@${ENV_COLOR_RESET}"
}
printError() {
    echo -e "${ENV_COLOR_B_RED}[ERROR] $@${ENV_COLOR_RESET}"
}

callAndLog () {
    $*
    if [[ $? -eq ${ENV_SUCCEED} ]]; then
        logInfo "$@"
        return ${ENV_SUCCEED}
    else
        logError "$@ EXECUTE FAILED"
        return ${ENV_FAILED}
    fi
}

# ------------------------------------------------------------------------------ functions

# 打印头部信息
printHeadInfo() {
printf "${C_B_BLUE}\n"
cat << EOF
###################################################################################
# 欢迎使用 Dunwu Shell 环境初始化脚本(设置环境配置、安装基本的命令工具)
# 适用于 Linux CentOS 环境
# @author: Zhang Peng
###################################################################################
EOF
printf "${C_RESET}\n"
}

LINUX_SCRIPTS_DIR=$(cd `dirname $0`; pwd)
menus=( "替换yum镜像" "安装基本的命令工具" "安装常用libs" "系统配置" "全部执行" "退出" )
main() {
	PS3="请输入命令编号:"
	select item in "${menus[@]}"
	do
	case ${item} in
		"替换yum镜像")
			sh ${LINUX_SCRIPTS_DIR}/sys/change-yum-repo.sh
			main ;;
		"安装基本的命令工具")
			sh ${LINUX_SCRIPTS_DIR}/sys/install-tools.sh
			main ;;
		"安装常用libs")
			sh ${LINUX_SCRIPTS_DIR}/sys/install-libs.sh
			main ;;
		"系统配置")
			sh ${LINUX_SCRIPTS_DIR}/sys/sys-settings.sh ${LINUX_SCRIPTS_DIR}/sys
			main ;;
		"全部执行")
			sh ${LINUX_SCRIPTS_DIR}/sys/change-yum-repo.sh
			sh ${LINUX_SCRIPTS_DIR}/sys/install-tools.sh
			sh ${LINUX_SCRIPTS_DIR}/sys/install-libs.sh
			sh ${LINUX_SCRIPTS_DIR}/sys/sys-settings.sh ${LINUX_SCRIPTS_DIR}/sys
			logInfo "执行完毕,退出" ;;
		"退出")
			exit 0 ;;
		*)
			logWarn "输入项不支持!"
			main ;;
	esac
	break
	done
}

# ------------------------------------------------------------------------------ main

printHeadInfo
main


================================================
FILE: codes/linux/libtest/README.md
================================================
# Git 脚本工具

这里汇总一些常用的、简单的 git shell 脚本。

更多功能强大的工具,可以参考 [资源](#资源)

## 资源

- [git-extras](https://github.com/tj/git-extras) - 丰富的 git 扩展支持
- [gitflow](https://github.com/nvie/gitflow) - git-flow shell 版本
- [gitflow-avh](https://github.com/petervanderdoes/gitflow-avh) - git-flow shell 版本

================================================
FILE: codes/linux/libtest/env-test.sh
================================================
#!/usr/bin/env bash

# 装载其它库
source ../lib/utils.sh

# ------------------------------------------------------------------------------ 颜色变量测试
printf "${C_B_YELLOW}测试彩色打印:${C_RESET}\n"

printf "${C_BLACK}Hello.${C_RESET}\n"
printf "${C_RED}Hello.${C_RESET}\n"
printf "${C_GREEN}Hello.${C_RESET}\n"
printf "${C_YELLOW}Hello.${C_RESET}\n"
printf "${C_BLUE}Hello.${C_RESET}\n"
printf "${C_MAGENTA}Hello.${C_RESET}\n"
printf "${C_CYAN}Hello.${C_RESET}\n"

printf "${C_B_BLACK}Hello.${C_RESET}\n"
printf "${C_B_RED}Hello.${C_RESET}\n"
printf "${C_B_GREEN}Hello.${C_RESET}\n"
printf "${C_B_YELLOW}Hello.${C_RESET}\n"
printf "${C_B_BLUE}Hello.${C_RESET}\n"
printf "${C_B_MAGENTA}Hello.${C_RESET}\n"
printf "${C_B_CYAN}Hello.${C_RESET}\n"

printf "${C_U_BLACK}Hello.${C_RESET}\n"
printf "${C_U_RED}Hello.${C_RESET}\n"
printf "${C_U_GREEN}Hello.${C_RESET}\n"
printf "${C_U_YELLOW}Hello.${C_RESET}\n"
printf "${C_U_BLUE}Hello.${C_RESET}\n"
printf "${C_U_MAGENTA}Hello.${C_RESET}\n"
printf "${C_U_CYAN}Hello.${C_RESET}\n"

printf "${C_BG_BLACK}Hello.${C_RESET}\n"
printf "${C_BG_RED}Hello.${C_RESET}\n"
printf "${C_BG_GREEN}Hello.${C_RESET}\n"
printf "${C_BG_YELLOW}Hello.${C_RESET}\n"
printf "${C_BG_BLUE}Hello.${C_RESET}\n"
printf "${C_BG_MAGENTA}Hello.${C_RESET}\n"
printf "${C_BG_CYAN}Hello.${C_RESET}\n"



================================================
FILE: codes/linux/libtest/git-check.sh
================================================
#!/usr/bin/env bash

source ../lib/utils.sh
source ../lib/git.sh

##################################### MAIN #####################################
if [[ $1 ]]; then
    DIR=$1
else
    DIR=$(pwd)
fi

printInfo "Current path is: ${DIR}."

# 判断是否为 git 项目
checkGit ${DIR}
if [[ "${YES}" == "$?" ]]; then
    printInfo "${DIR} is git project."
else
    printError "${DIR} is not git project."
fi

# 获取 git 分支
getGitLocalBranch
printInfo "git local branch: ${GIT_LOCAL_BRANCH}"
getGitOriginBranch
printInfo "git origin branch: ${GIT_ORIGIN_BRANCH}"


================================================
FILE: codes/linux/libtest/git-update.sh
================================================
#!/usr/bin/env bash

source ../lib/utils.sh
source ../lib/git.sh

doCloneOrPullGit() {
    cloneOrPullGit $1 $2 $3 $4 $5
    if [[ "$?" == "${SUCCEED}" ]]; then
        printf "\n${C_GREEN}>>>> Update git project [$2/$3] succeed.${C_RESET}\n"
        return ${SUCCEED}
    else
        printf "\n${C_RED}>>>> Update git project [$2/$3] failed.${C_RESET}\n"
        return ${FAILED}
    fi
}

##################################### MAIN #####################################
ROOT=$(dirname ${BASH_SOURCE[0]})

# 这里需要根据实际情况替换 Git 仓库、项目组、项目、代码分支
REPOSITORY="git@gitee.com"

printf "${C_CYAN}Current path is ${ROOT}.${C_RESET}\n"

doCloneOrPullGit ${REPOSITORY} turnon linux-tutorial master ${ROOT}
r1=$?
doCloneOrPullGit ${REPOSITORY} turnon nginx-tutorial master ${ROOT}
r2=$?

if [[ "${r1}" == "${SUCCEED}" && "${r2}" == "${SUCCEED}" ]]; then
    printf "\n${C_B_GREEN}<<<< Init workspace Succeed.${C_RESET}\n\n"
    exit ${SUCCEED}
else
    printf "\n${C_B_RED}<<<< Init workspace Failed.${C_RESET}\n\n"
    exit ${FAILED}
fi


================================================
FILE: codes/linux/libtest/nodejs-test.sh
================================================
#!/usr/bin/env bash

# 装载其它库
source ../lib/nodejs.sh

# ------------------------------------------------------------------------------
ROOT=$(pwd)

path=${ROOT}
if [[ $1 ]]; then
    path=$1
fi

version=10.15.0
if [[ $2 ]]; then
    version=$2
fi

buildNodejsProject ${path} ${version}


================================================
FILE: codes/linux/soft/README.md
================================================
# 服务安装配置

<!-- TOC depthFrom:2 depthTo:3 -->

- [oh-my-zsh 安装](#oh-my-zsh-安装)
- [JDK8 安装](#jdk8-安装)
- [Maven 安装配置](#maven-安装配置)
- [Node.js 安装](#nodejs-安装)
- [MongoDB 安装](#mongodb-安装)
- [Redis 安装配置](#redis-安装配置)
- [Tomcat8 安装](#tomcat8-安装)
- [Kafka 安装](#kafka-安装)
- [RocketMQ 安装](#rocketmq-安装)
- [Nacos 安装](#nacos-安装)
- [ZooKeeper 安装](#zookeeper-安装)
- [Nginx 运维](#nginx-安装)
- [Fastdfs 安装](#fastdfs-安装)
- [Docker 安装](#docker-安装)

<!-- /TOC -->

## oh-my-zsh 安装

说明:

安装 [oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh)

使用方法

执行以下任意命令即可执行安装脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/zsh-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/zsh-install.sh | bash
```

## JDK8 安装

说明:

JDK8 会被安装到 `/usr/lib/jvm/java` 路径。

使用方法:

执行以下任意命令即可执行安装脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/jdk8-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/jdk8-install.sh | bash
```

## Maven 安装配置

说明:

- 脚本会下载解压 maven `3.6.0` 到 `/opt/maven` 路径下。
- 备份并替换 `settings.xml`,使用 aliyun 镜像加速 maven。

使用方法:

执行以下任意命令即可执行安装脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/maven-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/maven-install.sh | bash
```

## Node.js 安装

说明:

脚本会先安装 nvm(nodejs 版本管理器),并通过 nvm 安装 nodejs `10.15.2`。

使用方法:

执行以下任意命令即可执行安装脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/nodejs-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/nodejs-install.sh | bash
```

## MongoDB 安装

说明:

下载 mongodb `4.0.9` 并解压安装到 `/opt/mongodb` 路径下。

使用方法:

执行以下任意命令即可执行安装脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/mongodb-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/mongodb-install.sh | bash
```

## Redis 安装配置

**安装说明**

- 采用编译方式安装 Redis, 并将其注册为 systemd 服务
- 安装路径为:`/usr/local/redis`
- 默认下载安装 `5.0.4` 版本,端口号为:`6379`,密码为空

**使用方法**

- 默认安装 - 执行以下任意命令即可:

```shell
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
```

- 自定义安装 - 下载脚本到本地,并按照以下格式执行:


```shell
sh redis-install.sh [version] [port] [password]
```

参数说明:

- `version` - redis 版本号
- `port` - redis 服务端口号
- `password` - 访问密码

## Tomcat8 安装

说明:

下载 tomcat `8.5.28` 并解压安装到 `/opt/tomcat` 路径下。

使用方法:

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/tomcat8-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/tomcat8-install.sh | bash
```

## Kafka 安装

说明:

下载 kafka `2.2.0` 并解压安装到 `/opt/kafka` 路径下。

使用方法:执行以下任意命令即可执行脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/kafka-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/kafka-install.sh | bash
```

## RocketMQ 安装

说明:

下载 rocketmq `4.5.0` 并解压安装到 `/opt/rocketmq` 路径下。

使用方法:执行以下任意命令即可执行脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/rocketmq-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/rocketmq-install.sh | bash
```

## Nacos 安装

说明:

下载 Nacos `1.0.0` 并解压安装到 `/opt/nacos` 路径下。

使用方法:执行以下任意命令即可执行脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/nacos-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/nacos-install.sh | bash
```

## ZooKeeper 安装

说明:

下载 zookeeper `3.4.12` 并解压安装到 `/opt/zookeeper` 路径下。

使用方法:执行以下任意命令即可执行脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/zookeeper-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/zookeeper-install.sh | bash
```

## Nginx 运维

**安装说明**

- 采用编译方式安装 Nginx, 并将其注册为 systemd 服务
- 安装路径为:`/usr/local/nginx`
- 默认下载安装 `1.16.0` 版本

**使用方法**

- 默认安装 - 执行以下任意命令即可:


```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/nginx-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/nginx-install.sh | bash
```

- 自定义安装 - 下载脚本到本地,并按照以下格式执行:

```bash
sh nginx-install.sh [version]
```

## Fastdfs 安装

说明:

采用编译方式安装 Fastdfs

下载 Fastdfs 并解压安装到 `/opt/fdfs` 路径下。

使用方法:执行以下任意命令即可执行脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/fastdfs-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/fastdfs-install.sh | bash
```

## Docker 安装

说明:

使用方法:执行以下任意命令即可执行脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/docker-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/docker-install.sh | bash
```

## FastDFS 安装

说明:

使用方法:执行以下任意命令即可执行脚本。

```shell
curl -o- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/fastdfs-install.sh | bash
wget -qO- https://gitee.com/turnon/linux-tutorial/raw/master/codes/linux/soft/fastdfs-install.sh | bash
```


================================================
FILE: codes/linux/soft/arthas-install.sh
================================================
#!/usr/bin/env bash

# ----------------------------------------------------------------------------------
# 控制台颜色
BLACK="\033[1;30m"
RED="\033[1;31m"
GREEN="\033[1;32m"
YELLOW="\033[1;33m"
BLUE="\033[1;34m"
PURPLE="\033[1;35m"
CYAN="\033[1;36m"
RESET="$(tput sgr0)"
# ----------------------------------------------------------------------------------

printf "${PURPLE}"
cat << EOF
# ----------------------------------------------------------------------------------
# Arthas 安装脚本
# @author: Zhang Peng
# ----------------------------------------------------------------------------------
EOF
printf "${RESET}"

printf "${BLUE}>>>>>>>> begin.\n${RESET}"

root=/opt/arthas
if [[ -n $1 ]]; then
	root=$1
fi

mkdir -p ${root}
curl -o ${root}/arthas-boot.jar https://alibaba.github.io/arthas/arthas-boot.jar

printf "${GREEN}[OK]\n${RESET}"
printf "${BLUE}<<<<<<<< end.\n${RESET}"


================================================
FILE: codes/linux/soft/config/fastdfs/client.conf
================================================
# connect timeout in seconds
# default value is 30s
connect_timeout=30

# network timeout in seconds
# default value is 30s
network_timeout=60

# the base path to store log files
base_path=/home/fdfs

# tracker_server can ocur more than once, and tracker_server format is
#  "host:port", host can be hostname or ip address
tracker_server=127.0.0.1:22122

#standard log level as syslog, case insensitive, value list:
### emerg for emergency
### alert
### crit for critical
### error
### warn for warning
### notice
### info
### debug
log_level=info

# if use connection pool
# default value is false
# since V4.05
use_connection_pool = false

# connections whose the idle time exceeds this time will be closed
# unit: second
# default value is 3600
# since V4.05
connection_pool_max_idle_time = 3600

# if load FastDFS parameters from tracker server
# since V4.05
# default value is false
load_fdfs_parameters_from_tracker=false

# if use storage ID instead of IP address
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# default value is false
# since V4.05
use_storage_id = false

# specify storage ids filename, can use relative or absolute path
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# since V4.05
storage_ids_filename = storage_ids.conf


#HTTP settings
http.tracker_server_port=80

#use "#include" directive to include HTTP other settiongs
##include http.conf



================================================
FILE: codes/linux/soft/config/fastdfs/storage.conf
================================================
# is this config file disabled
# false for enabled
# true for disabled
disabled=false

# the name of the group this storage server belongs to
#
# comment or remove this item for fetching from tracker server,
# in this case, use_storage_id must set to true in tracker.conf,
# and storage_ids.conf must be configed correctly.
group_name=group1

# bind an address of this host
# empty for bind all addresses of this host
bind_addr=

# if bind an address of this host when connect to other servers 
# (this storage server as a client)
# true for binding the address configed by above parameter: "bind_addr"
# false for binding any address of this host
client_bind=true

# the storage server port
port=23000

# connect timeout in seconds
# default value is 30s
connect_timeout=10

# network timeout in seconds
# default value is 30s
network_timeout=60

# heart beat interval in seconds
heart_beat_interval=30

# disk usage report interval in seconds
stat_report_interval=60

# the base path to store data and log files
base_path=/home/fdfs

# max concurrent connections the server supported
# default value is 256
# more max_connections means more memory will be used
# you should set this parameter larger, eg. 10240
max_connections=1024

# the buff size to recv / send data
# this parameter must more than 8KB
# default value is 64KB
# since V2.00
buff_size = 256KB

# accept thread count
# default value is 1
# since V4.07
accept_threads=1

# work thread count, should <= max_connections
# work thread deal network io
# default value is 4
# since V2.00
work_threads=4

# if disk read / write separated
##  false for mixed read and write
##  true for separated read and write
# default value is true
# since V2.00
disk_rw_separated = true

# disk reader thread count per store base path
# for mixed read / write, this parameter can be 0
# default value is 1
# since V2.00
disk_reader_threads = 1

# disk writer thread count per store base path
# for mixed read / write, this parameter can be 0
# default value is 1
# since V2.00
disk_writer_threads = 1

# when no entry to sync, try read binlog again after X milliseconds
# must > 0, default value is 200ms
sync_wait_msec=50

# after sync a file, usleep milliseconds
# 0 for sync successively (never call usleep)
sync_interval=0

# storage sync start time of a day, time format: Hour:Minute
# Hour from 0 to 23, Minute from 0 to 59
sync_start_time=00:00

# storage sync end time of a day, time format: Hour:Minute
# Hour from 0 to 23, Minute from 0 to 59
sync_end_time=23:59

# write to the mark file after sync N files
# default value is 500
write_mark_file_freq=500

# path(disk or mount point) count, default value is 1
store_path_count=1

# store_path#, based 0, if store_path0 not exists, it's value is base_path
# the paths must be exist
store_path0=/home/fdfs
#store_path1=/home/fdfs2

# subdir_count  * subdir_count directories will be auto created under each
# store_path (disk), value can be 1 to 256, default value is 256
subdir_count_per_path=256

# tracker_server can ocur more than once, and tracker_server format is
#  "host:port", host can be hostname or ip address
tracker_server=127.0.0.1:22122

#standard log level as syslog, case insensitive, value list:
### emerg for emergency
### alert
### crit for critical
### error
### warn for warning
### notice
### info
### debug
log_level=info

#unix group name to run this program,
#not set (empty) means run by the group of current user
run_by_group=

#unix username to run this program,
#not set (empty) means run by current user
run_by_user=

# allow_hosts can ocur more than once, host can be hostname or ip address,
# "*" (only one asterisk) means match all ip addresses
# we can use CIDR ips like 192.168.5.64/26
# and also use range like these: 10.0.1.[0-254] and host[01-08,20-25].domain.com
# for example:
# allow_hosts=10.0.1.[1-15,20]
# allow_hosts=host[01-08,20-25].domain.com
# allow_hosts=192.168.5.64/26
allow_hosts=*

# the mode of the files distributed to the data path
# 0: round robin(default)
# 1: random, distributted by hash code
file_distribute_path_mode=0

# valid when file_distribute_to_path is set to 0 (round robin),
# when the written file count reaches this number, then rotate to next path
# default value is 100
file_distribute_rotate_count=100

# call fsync to disk when write big file
# 0: never call fsync
# other: call fsync when written bytes >= this bytes
# default value is 0 (never call fsync)
fsync_after_written_bytes=0

# sync log buff to disk every interval seconds
# must > 0, default value is 10 seconds
sync_log_buff_interval=10

# sync binlog buff / cache to disk every interval seconds
# default value is 60 seconds
sync_binlog_buff_interval=10

# sync storage stat info to disk every interval seconds
# default value is 300 seconds
sync_stat_file_interval=300

# thread stack size, should >= 512KB
# default value is 512KB
thread_stack_size=512KB

# the priority as a source server for uploading file.
# the lower this value, the higher its uploading priority.
# default value is 10
upload_priority=10

# the NIC alias prefix, such as eth in Linux, you can see it by ifconfig -a
# multi aliases split by comma. empty value means auto set by OS type
# default values is empty
if_alias_prefix=

# if check file duplicate, when set to true, use FastDHT to store file indexes
# 1 or yes: need check
# 0 or no: do not check
# default value is 0
check_file_duplicate=0

# file signature method for check file duplicate
## hash: four 32 bits hash code
## md5: MD5 signature
# default value is hash
# since V4.01
file_signature_method=hash

# namespace for storing file indexes (key-value pairs)
# this item must be set when check_file_duplicate is true / on
key_namespace=FastDFS

# set keep_alive to 1 to enable persistent connection with FastDHT servers
# default value is 0 (short connection)
keep_alive=0

# you can use "#include filename" (not include double quotes) directive to
# load FastDHT server list, when the filename is a relative path such as
# pure filename, the base path is the base path of current/this config file.
# must set FastDHT server list when check_file_duplicate is true / on
# please see INSTALL of FastDHT for detail
##include /home/yuqing/fastdht/conf/fdht_servers.conf

# if log to access log
# default value is false
# since V4.00
use_access_log = false

# if rotate the access log every day
# default value is false
# since V4.00
rotate_access_log = false

# rotate access log time base, time format: Hour:Minute
# Hour from 0 to 23, Minute from 0 to 59
# default value is 00:00
# since V4.00
access_log_rotate_time=00:00

# if rotate the error log every day
# default value is false
# since V4.02
rotate_error_log = false

# rotate error log time base, time format: Hour:Minute
# Hour from 0 to 23, Minute from 0 to 59
# default value is 00:00
# since V4.02
error_log_rotate_time=00:00

# rotate access log when the log file exceeds this size
# 0 means never rotates log file by log file size
# default value is 0
# since V4.02
rotate_access_log_size = 0

# rotate error log when the log file exceeds this size
# 0 means never rotates log file by log file size
# default value is 0
# since V4.02
rotate_error_log_size = 0

# keep days of the log files
# 0 means do not delete old log files
# default value is 0
log_file_keep_days = 0

# if skip the invalid record when sync file
# default value is false
# since V4.02
file_sync_skip_invalid_record=false

# if use connection pool
# default value is false
# since V4.05
use_connection_pool = false

# connections whose the idle time exceeds this time will be closed
# unit: second
# default value is 3600
# since V4.05
connection_pool_max_idle_time = 3600

# use the ip address of this storage server if domain_name is empty,
# else this domain name will ocur in the url redirected by the tracker server
http.domain_name=

# the port of the web server on this storage server
http.server_port=7001


================================================
FILE: codes/linux/soft/config/fastdfs/tracker.conf
================================================
# is this config file disabled
# false for enabled
# true for disabled
disabled=false

# bind an address of this host
# empty for bind all addresses of this host
bind_addr=

# the tracker server port
port=22122

# connect timeout in seconds
# default value is 30s
connect_timeout=10

# network timeout in seconds
# default value is 30s
network_timeout=60

# the base path to store data and log files
base_path=/home/fdfs

# max concurrent connections this server supported
# you should set this parameter larger, eg. 102400
max_connections=1024

# accept thread count
# default value is 1
# since V4.07
accept_threads=1

# work thread count, should <= max_connections
# default value is 4
# since V2.00
work_threads=4

# min buff size
# default value 8KB
min_buff_size = 8KB

# max buff size
# default value 128KB
max_buff_size = 128KB

# the method of selecting group to upload files
# 0: round robin
# 1: specify group
# 2: load balance, select the max free space group to upload file
store_lookup=2

# which group to upload file
# when store_lookup set to 1, must set store_group to the group name
store_group=group2

# which storage server to upload file
# 0: round robin (default)
# 1: the first server order by ip address
# 2: the first server order by priority (the minimal)
# Note: if use_trunk_file set to true, must set store_server to 1 or 2
store_server=0

# which path(means disk or mount point) of the storage server to upload file
# 0: round robin
# 2: load balance, select the max free space path to upload file
store_path=0

# which storage server to download file
# 0: round robin (default)
# 1: the source storage server which the current file uploaded to
download_server=0

# reserved storage space for system or other applications.
# if the free(available) space of any stoarge server in
# a group <= reserved_storage_space,
# no file can be uploaded to this group.
# bytes unit can be one of follows:
### G or g for gigabyte(GB)
### M or m for megabyte(MB)
### K or k for kilobyte(KB)
### no unit for byte(B)
### XX.XX% as ratio such as reserved_storage_space = 10%
reserved_storage_space = 10%

#standard log level as syslog, case insensitive, value list:
### emerg for emergency
### alert
### crit for critical
### error
### warn for warning
### notice
### info
### debug
log_level=info

#unix group name to run this program,
#not set (empty) means run by the group of current user
run_by_group=

#unix username to run this program,
#not set (empty) means run by current user
run_by_user=

# allow_hosts can ocur more than once, host can be hostname or ip address,
# "*" (only one asterisk) means match all ip addresses
# we can use CIDR ips like 192.168.5.64/26
# and also use range like these: 10.0.1.[0-254] and host[01-08,20-25].domain.com
# for example:
# allow_hosts=10.0.1.[1-15,20]
# allow_hosts=host[01-08,20-25].domain.com
# allow_hosts=192.168.5.64/26
allow_hosts=*

# sync log buff to disk every interval seconds
# default value is 10 seconds
sync_log_buff_interval = 10

# check storage server alive interval seconds
check_active_interval = 120

# thread stack size, should >= 64KB
# default value is 64KB
thread_stack_size = 64KB

# auto adjust when the ip address of the storage server changed
# default value is true
storage_ip_changed_auto_adjust = true

# storage sync file max delay seconds
# default value is 86400 seconds (one day)
# since V2.00
storage_sync_file_max_delay = 86400

# the max time of storage sync a file
# default value is 300 seconds
# since V2.00
storage_sync_file_max_time = 300

# if use a trunk file to store several small files
# default value is false
# since V3.00
use_trunk_file = false

# the min slot size, should <= 4KB
# default value is 256 bytes
# since V3.00
slot_min_size = 256

# the max slot size, should > slot_min_size
# store the upload file to trunk file when it's size <=  this value
# default value is 16MB
# since V3.00
slot_max_size = 16MB

# the trunk file size, should >= 4MB
# default value is 64MB
# since V3.00
trunk_file_size = 64MB

# if create trunk file advancely
# default value is false
# since V3.06
trunk_create_file_advance = false

# the time base to create trunk file
# the time format: HH:MM
# default value is 02:00
# since V3.06
trunk_create_file_time_base = 02:00

# the interval of create trunk file, unit: second
# default value is 38400 (one day)
# since V3.06
trunk_create_file_interval = 86400

# the threshold to create trunk file
# when the free trunk file size less than the threshold, will create
# the trunk files
# default value is 0
# since V3.06
trunk_create_file_space_threshold = 20G

# if check trunk space occupying when loading trunk free spaces
# the occupied spaces will be ignored
# default value is false
# since V3.09
# NOTICE: set this parameter to true will slow the loading of trunk spaces
# when startup. you should set this parameter to true when neccessary.
trunk_init_check_occupying = false

# if ignore storage_trunk.dat, reload from trunk binlog
# default value is false
# since V3.10
# set to true once for version upgrade when your version less than V3.10
trunk_init_reload_from_binlog = false

# the min interval for compressing the trunk binlog file
# unit: second
# default value is 0, 0 means never compress
# FastDFS compress the trunk binlog when trunk init and trunk destroy
# recommand to set this parameter to 86400 (one day)
# since V5.01
trunk_compress_binlog_min_interval = 0

# if use storage ID instead of IP address
# default value is false
# since V4.00
use_storage_id = false

# specify storage ids filename, can use relative or absolute path
# since V4.00
storage_ids_filename = storage_ids.conf

# id type of the storage server in the filename, values are:
## ip: the ip address of the storage server
## id: the server id of the storage server
# this paramter is valid only when use_storage_id set to true
# default value is ip
# since V4.03
id_type_in_filename = ip

# if store slave file use symbol link
# default value is false
# since V4.01
store_slave_file_use_link = false

# if rotate the error log every day
# default value is false
# since V4.02
rotate_error_log = false

# rotate error log time base, time format: Hour:Minute
# Hour from 0 to 23, Minute from 0 to 59
# default value is 00:00
# since V4.02
error_log_rotate_time=00:00

# rotate error log when the log file exceeds this size
# 0 means never rotates log file by log file size
# default value is 0
# since V4.02
rotate_error_log_size = 0

# keep days of the log files
# 0 means do not delete old log files
# default value is 0
log_file_keep_days = 0

# if use connection pool
# default value is false
# since V4.05
use_connection_pool = false

# connections whose the idle time exceeds this time will be closed
# unit: second
# default value is 3600
# since V4.05
connection_pool_max_idle_time = 3600

# HTTP port on this tracker server
http.server_port=7000

# check storage HTTP server alive interval seconds
# <= 0 for never check
# default value is 30
http.check_alive_interval=30

# check storage HTTP server alive type, values are:
#   tcp : connect to the storge server with HTTP port only,
#        do not request and get response
#   http: storage check alive url must return http status 200
# default value is tcp
http.check_alive_type=tcp

# check storage HTTP server alive uri/url
# NOTE: storage embed HTTP server support uri: /status.html
http.check_alive_uri=/status.html


================================================
FILE: codes/linux/soft/config/mysql/my.cnf
================================================
# -------------------------------------------------------------------------------
# Mysql 基本配置模板
# -------------------------------------------------------------------------------

[mysqld]
# GENERAL
# -------------------------------------------------------------------------------
server_id = 2
datadir = /var/lib/mysql
socket  = /var/lib/mysql/mysql.sock
pid_file = /var/lib/mysql/mysql.pid
user = mysql
port = 3306
default_storage_engine = InnoDB
default_time_zone = '+8:00'
character_set_server = utf8mb4
collation_server = utf8mb4_0900_ai_ci

# LOG
# -------------------------------------------------------------------------------
log_error = /var/log/mysql/mysql.log
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql_slow_query_log.log
long_query_time = 3
min_examined_row_limit = 100
expire_logs_days = 7

# InnoDB
# -------------------------------------------------------------------------------
innodb_buffer_pool_size = 4G
innodb_log_file_size = 128M
innodb_file_per_table = 1
innodb_flush_method = O_DIRECT

# MyIsam
# -------------------------------------------------------------------------------
key_buffer_size = 256M

# OTHER
# -------------------------------------------------------------------------------
tmp_table_size = 32M
max_heap_table_size = 32M
max_connections = 10000
open_files_limit = 65535

[client]
socket  = /var/lib/mysql/mysql.sock
port = 3306


================================================
FILE: codes/linux/soft/config/nginx/conf/fdfs.conf
================================================
server {
  listen       7001;    ## 该端口为storage.conf中的http.server_port相同
  server_name  localhost;
  location ~/group[0-9]/ {
    ngx_fastdfs_module;
  }
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   html;
  }
}


================================================
FILE: codes/linux/soft/config/nginx/nginx.conf
================================================
worker_processes 1;

error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
pid /usr/local/nginx/logs/nginx.pid;

events {
	worker_connections 1024;
}

http {
	include mime.types;
	include conf.d/*.conf;

	default_type application/octet-stream;

	log_format main '$remote_addr - $remote_user [$time_local] "$request" '
						'$status $body_bytes_sent "$http_referer" '
						'"$http_user_agent" "$http_x_forwarded_for"';
	#access_log logs/nginx-http-access.log;

	sendfile on;
	keepalive_timeout 65;

	client_max_body_size 20m;
	client_body_buffer_size 128k;

	#common header set
	proxy_http_version 1.1;
	proxy_set_header Host $host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header X-Forwarded-Proto $scheme;
	proxy_set_header Upgrade $http_upgrade;
	proxy_set_header Connection "upgrade";
}


================================================
FILE: codes/linux/soft/config/nginx/nginx.service
================================================
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target


================================================
FILE: codes/linux/soft/config/redis/cluster/27001/sentinel.conf
================================================
port 27001
daemonize yes
sentinel monitor redis-master 172.22.6.3 7001 2
sentinel down-after-milliseconds redis-master 5000
sentinel failover-timeout redis-master 900000
sentinel parallel-syncs redis-master 1
#sentinel auth-pass redis-master 123456
logfile /usr/local/redis/conf/27001/27001.log

================================================
FILE: codes/linux/soft/config/redis/cluster/27002/sentinel.conf
================================================
port 27002
daemonize yes
sentinel monitor redis-master 172.22.6.3 7002 2
sentinel down-after-milliseconds redis-master 5000
sentinel failover-timeout redis-master 900000
sentinel parallel-syncs redis-master 1
#sentinel auth-pass redis-master 123456
logfile /usr/local/redis/conf/27002/27002.log

================================================
FILE: codes/linux/soft/config/redis/cluster/27003/sentinel.conf
================================================
port 27003
daemonize yes
sentinel monitor redis-master 172.22.6.3 7003 2
sentinel down-after-milliseconds redis-master 5000
sentinel failover-timeout redis-master 900000
sentinel parallel-syncs redis-master 1
#sentinel auth-pass redis-master 123456
logfile /usr/local/redis/conf/27003/27003.log

================================================
FILE: codes/linux/soft/config/redis/cluster/27004/sentinel.conf
================================================
port 27004
daemonize yes
sentinel monitor redis-master 172.22.6.3 7007 2
sentinel down-after-milliseconds redis-master 5000
sentinel failover-timeout redis-master 900000
sentinel parallel-syncs redis-master 1
#sentinel auth-pass redis-master 123456
logfile /usr/local/redis/conf/27004/27004.log


================================================
FILE: codes/linux/soft/config/redis/cluster/27005/sentinel.conf
================================================
port 27005
daemonize yes
sentinel monitor redis-master 172.22.6.3 7008 2
sentinel down-after-milliseconds redis-master 5000
sentinel failover-timeout redis-master 900000
sentinel parallel-syncs redis-master 1
#sentinel auth-pass redis-master 123456
logfile /usr/local/redis/conf/27005/27005.log


================================================
FILE: codes/linux/soft/config/redis/cluster/27006/sentinel.conf
================================================
port 27006
daemonize yes
sentinel monitor redis-master 172.22.6.3 7009 2
sentinel down-after-milliseconds redis-master 5000
sentinel failover-timeout redis-master 900000
sentinel parallel-syncs redis-master 1
#sentinel auth-pass redis-master 123456
logfile /usr/local/redis/conf/27006/27006.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7001/redis.conf
================================================
port 7001
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7001/7001.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7001
pidfile /usr/local/redis/conf/7001/7001.pid
logfile /usr/local/redis/conf/7001/7001.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7002/redis.conf
================================================
port 7002
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7002/7002.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7002
pidfile /usr/local/redis/conf/7002/7002.pid
logfile /usr/local/redis/conf/7002/7002.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7003/redis.conf
================================================
port 7003
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7003/7003.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7003
pidfile /usr/local/redis/conf/7003/7003.pid
logfile /usr/local/redis/conf/7003/7003.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7004/redis.conf
================================================
port 7004
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7004/7004.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7004
pidfile /usr/local/redis/conf/7004/7004.pid
logfile /usr/local/redis/conf/7004/7004.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7005/redis.conf
================================================
port 7005
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7005/7005.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7005
pidfile /usr/local/redis/conf/7005/7005.pid
logfile /usr/local/redis/conf/7005/7005.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7006/redis.conf
================================================
port 7006
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7006/7006.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7006
pidfile /usr/local/redis/conf/7006/7006.pid
logfile /usr/local/redis/conf/7006/7006.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7007/redis.conf
================================================
port 7007
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7007/7007.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7007
pidfile /usr/local/redis/conf/7007/7007.pid
logfile /usr/local/redis/conf/7007/7007.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7008/redis.conf
================================================
port 7008
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7008/7008.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7008
pidfile /usr/local/redis/conf/7008/7008.pid
logfile /usr/local/redis/conf/7008/7008.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7009/redis.conf
================================================
port 7009
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7009/7009.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7009
pidfile /usr/local/redis/conf/7009/7009.pid
logfile /usr/local/redis/conf/7009/7009.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7010/redis.conf
================================================
port 7010
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7010/7010.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7010
pidfile /usr/local/redis/conf/7010/7010.pid
logfile /usr/local/redis/conf/7010/7010.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7011/redis.conf
================================================
port 7011
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7011/7011.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7011
pidfile /usr/local/redis/conf/7011/7011.pid
logfile /usr/local/redis/conf/7011/7011.log


================================================
FILE: codes/linux/soft/config/redis/cluster/7012/redis.conf
================================================
port 7012
bind 172.22.6.3
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7012/7012.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7012
pidfile /usr/local/redis/conf/7012/7012.pid
logfile /usr/local/redis/conf/7012/7012.log


================================================
FILE: codes/linux/soft/config/redis/cluster/README.md
================================================
# Redis 集群配置

## 使用方式

集群拓扑:

- 三主三从
- 三哨兵

启动方式:

- 先执行 redis-cluster.sh,会自动根据 7001 ~ 7006 目录启动服务器,并将其配置为集群。
- 再执行 start-sentinel.sh,会根据 27001 ~ 27003 目录启动哨兵,监听集群中的三个主节点。

## 配置

(1)集群服务器配置 redis.conf

```
port 7001
bind 0.0.0.0
daemonize yes

cluster-enabled yes
cluster-config-file /usr/local/redis/conf/7001/7001.conf
cluster-node-timeout 10000

appendonly yes
dir /usr/local/redis/conf/7001
pidfile /usr/local/redis/conf/7001/7001.pid
logfile /usr/local/redis/conf/7001/7001.log
```

端口号、配置目录(`/usr/local/redis/conf`)根据实际情况修改。

(2)哨兵服务器配置 sentinel.conf

```
port 27003
daemonize yes
sentinel monitor redis-master 172.22.6.3 7003 2
sentinel down-after-milliseconds redis-master 5000
sentinel failover-timeout redis-master 900000
sentinel parallel-syncs redis-master 1
#sentinel auth-pass redis-master 123456
logfile /usr/local/redis/conf/27003/27003.log
```

端口号、配置目录(`/usr/local/redis/conf`)根据实际情况修改。

最重要的配置在于:sentinel monitor redis-master 172.22.6.3 7003 2

表示监听的服务器集群名叫 redis-master,当前哨兵监听的服务器节点是:172.22.6.3:7003,这个节点如果是主节点,一旦宕机,选举新的主节点,需要至少 2 个哨兵同意。


================================================
FILE: codes/linux/soft/config/redis/cluster/redis-cluster.sh
================================================
#!/usr/bin/env bash

# Settings
HOST="172.22.6.3"
PORT=7000
TIMEOUT=2000
NODES=6
REPLICAS=1
ENDPORT=$((PORT+NODES))

# You may want to put the above config parameters into config.sh in order to
# override the defaults without modifying this script.

if [[ -a config.sh ]]
then
    source "config.sh"
fi

if [[ "$1" == "create" ]]
then
    HOSTLIST=""
    while [[ $((PORT < ENDPORT)) != "0" ]]; do
        PORT=$((PORT+1))
        HOSTLIST="$HOSTLIST $HOST:$PORT"
    done
    /opt/redis/src/redis-cli --cluster create ${HOSTLIST} --cluster-replicas ${REPLICAS}
    exit 0
fi

if [[ "$1" == "start" ]]
then
    while [[ $((PORT < ENDPORT)) != "0" ]]; do
        PORT=$((PORT+1))
        echo "Starting $PORT"
        /opt/redis/src/redis-server /usr/local/redis/conf/${PORT}/redis.conf
    done
    exit 0
fi

if [[ "$1" == "stop" ]]
then
    while [[ $((PORT < ENDPORT)) != "0" ]]; do
        PORT=$((PORT+1))
        echo "Stopping $PORT"
        /opt/redis/src/redis-cli -p ${PORT} shutdown nosave
    done
    exit 0
fi

if [[ "$1" == "watch" ]]
then
    PORT=$((PORT+1))
    while [ 1 ]; do
        clear
        date
        /opt/redis/src/redis-cli -p ${PORT} cluster nodes | head -30
        sleep 1
    done
    exit 0
fi

if [[ "$1" == "tail" ]]
then
    INSTANCE=$2
    PORT=$((PORT+INSTANCE))
    tail -f ${PORT}.log
    exit 0
fi

if [[ "$1" == "call" ]]
then
    while [[ $((PORT < ENDPORT)) != "0" ]]; do
        PORT=$((PORT+1))
        /opt/redis/src/redis-cli -p ${PORT} $2 $3 $4 $5 $6 $7 $8 $9
    done
    exit 0
fi

if [[ "$1" == "clean" ]]
then
    rm -rf *.log
    rm -rf appendonly*.aof
    rm -rf dump*.rdb
    rm -rf nodes*.conf
    exit 0
fi

if [[ "$1" == "clean-logs" ]]
then
    rm -rf *.log
    exit 0
fi

echo "Usage: $0 [start|create|stop|watch|tail|clean]"
echo "start       -- Launch Redis Cluster instances."
echo "create      -- Create a cluster using redis-cli --cluster create."
echo "stop        -- Stop Redis Cluster instances."
echo "watch       -- Show CLUSTER NODES output (first 30 lines) of first node."
echo "tail <id>   -- Run tail -f of instance at base port + ID."
echo "clean       -- Remove all instances data, logs, configs."
echo "clean-logs  -- Remove just instances logs."


================================================
FILE: codes/linux/soft/config/redis/cluster/redis-cluster2.sh
================================================
#!/usr/bin/env bash

# Settings
HOST="172.22.6.3"
PORT=7000
TIMEOUT=2000
NODES=12
REPLICAS=1
ENDPORT=$((PORT+NODES))

# You may want to put the above config parameters into config.sh in order to
# override the defaults without modifying this script.

if [[ -a config.sh ]]
then
    source "config.sh"
fi

if [[ "$1" == "create" ]]
then
    HOSTLIST=""
    while [[ $((PORT < ENDPORT)) != "0" ]]; do
        PORT=$((PORT+1))
        HOSTLIST="$HOSTLIST $HOST:$PORT"
    done
    /opt/redis/src/redis-cli --cluster create ${HOSTLIST} --cluster-replicas ${REPLICAS}
    exit 0
fi

if [[ "$1" == "start" ]]
then
    while [[ $((PORT < ENDPORT)) != "0" ]]; do
        PORT=$((PORT+1))
        echo "Starting $PORT"
        /opt/redis/src/redis-server /usr/local/redis/conf/${PORT}/redis.conf
    done
    exit 0
fi

if [[ "$1" == "stop" ]]
then
    while [[ $((PORT < ENDPORT)) != "0" ]]; do
        PORT=$((PORT+1))
        echo "Stopping $PORT"
        /opt/redis/src/redis-cli -p ${PORT} shutdown nosave
    done
    exit 0
fi

if [[ "$1" == "watch" ]]
then
    PORT=$((PORT+1))
    while [ 1 ]; do
        clear
        date
        /opt/redis/src/redis-cli -p ${PORT} cluster nodes | head -30
        sleep 1
    done
    exit 0
fi

if [[ "$1" == "tail" ]]
then
    INSTANCE=$2
    PORT=$((PORT+INSTANCE))
    tail -f ${PORT}.log
    exit 0
fi

if [[ "$1" == "call" ]]
then
    while [[ $((PORT < ENDPORT)) != "0" ]]; do
        PORT=$((PORT+1))
        /opt/redis/src/redis-cli -p ${PORT} $2 $3 $4 $5 $6 $7 $8 $9
    done
    exit 0
fi

if [[ "$1" == "clean" ]]
then
    rm -rf *.log
    rm -rf appendonly*.aof
    rm -rf dump*.rdb
    rm -rf nodes*.conf
    exit 0
fi

if [[ "$1" == "clean-logs" ]]
then
    rm -rf *.log
    exit 0
fi

echo "Usage: $0 [start|create|stop|watch|tail|clean]"
echo "start       -- Launch Redis Cluster instances."
echo "create      -- Create a cluster using redis-cli --cluster create."
echo "stop        -- Stop Redis Cluster instances."
echo "watch       -- Show CLUSTER NODES output (first 30 lines) of first node."
echo "tail <id>   -- Run tail -f of instance at base port + ID."
echo "clean       -- Remove all instances data, logs, configs."
echo "clean-logs  -- Remove just instances logs."


================================================
FILE: codes/linux/soft/config/redis/cluster/start-cluster.sh
================================================
#!/usr/bin/env bash

PORT=6380
NODES=6
ENDPORT=$((PORT+NODES))

# 启动 4 个 redis server
while [[ $((PORT < ENDPORT)) != "0" ]]; do
    PORT=$((PORT+1))
    echo "Starting $PORT"
    /opt/redis/src/redis-server /usr/local/redis/conf/${PORT}/redis.conf
done

# 创建集群模式,设置副本为 1
# redis cluster 会自动将 4 个节点设置为 一主一从 模式,并且为两个主节点做数据分片
/opt/redis/src/redis-cli --cluster create 172.22.6.3:6381 172.22.6.3:6382 172.22.6.3:6383 172.22.6.3:6384 172.22.6.3:6385 172.22.6.3:6386 --cluster-replicas 1

# 启动哨兵
/opt/redis/src/redis-sentinel /usr/local/redis/conf/26381/sentinel.conf
/opt/redis/src/redis-sentinel /usr/local/redis/conf/26382/sentinel.conf
/opt/redis/src/redis-sentinel /usr/local/redis/conf/26383/sentinel.conf


================================================
FILE: codes/linux/soft/config/redis/cluster/start-cluster2.sh
================================================
#!/usr/bin/env bash

# 启动 4 个 redis server
/opt/redis/src/redis-server /usr/local/redis/conf/6381/redis.conf
/opt/redis/src/redis-server /usr/local/redis/conf/6382/redis.conf
/opt/redis/src/redis-server /usr/local/redis/conf/6383/redis.conf
/opt/redis/src/redis-server /usr/local/redis/conf/6384/redis.conf
/opt/redis/src/redis-server /usr/local/redis/conf/6385/redis.conf
/opt/redis/src/redis-server /usr/local/redis/conf/6386/redis.conf

# 创建集群模式,设置副本为 1
# redis cluster 会自动将 4 个节点设置为 一主一从 模式,并且为两个主节点做数据分片
/opt/redis/src/redis-cli --cluster create 172.22.6.3:6381 172.22.6.3:6382 172.22.6.3:6383 172.22.6.3:6384 172.22.6.3:6385 172.22.6.3:6386 --cluster-replicas 1

# 启动哨兵
/opt/redis/src/redis-sentinel /usr/local/redis/conf/26381/sentinel.conf
/opt/redis/src/redis-sentinel /usr/local/redis/conf/26382/sentinel.conf
/opt/redis/src/redis-sentinel /usr/local/redis/conf/26383/sentinel.conf


================================================
FILE: codes/linux/soft/config/redis/cluster/start-sentinel.sh
================================================
/opt/redis/src/redis-sentinel /usr/local/redis/conf/27001/sentinel.conf
/opt/redis/src/redis-sentinel /usr/local/redis/conf/27002/sentinel.conf
/opt/redis/src/redis-sentinel /usr/local/redis/conf/27003/sentinel.conf
/opt/redis/src/redis-sentinel /usr/local/redis/conf/27004/sentinel.conf
/opt/redis/src/redis-sentinel /usr/local/redis/conf/27005/sentinel.conf
/opt/redis/src/redis-sentinel /usr/local/redis/conf/27006/sentinel.conf


================================================
FILE: codes/linux/soft/config/redis/redis.conf
================================================
# Redis configuration file example.
#
# Note that in order to read the configuration file, Redis must be
# started with the file path as first argument:
#
# ./redis-server /path/to/redis.conf

# Note on units: when memory size is needed, it is possible to specify
# it in the usual form of 1k 5GB 4M and so forth:
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# units are case insensitive so 1GB 1Gb 1gB are all the same.

################################## INCLUDES ###################################

# Include one or more other config files here.  This is useful if you
# have a standard template that goes to all Redis servers but also need
# to customize a few per-server settings.  Include files can include
# other files, so use this wisely.
#
# Notice option "include" won't be rewritten by command "CONFIG REWRITE"
# from admin or Redis Sentinel. Since Redis always uses the last processed
# line as value of a configuration directive, you'd better put includes
# at the beginning of this file to avoid overwriting config change at runtime.
#
# If instead you are interested in using includes to override configuration
# options, it is better to use include as the last line.
#
# include /path/to/local.conf
# include /path/to/other.conf

################################## MODULES #####################################

# Load modules at startup. If the server is not able to load modules
# it will abort. It is possible to use multiple loadmodule directives.
#
# loadmodule /path/to/my_module.so
# loadmodule /path/to/other_module.so

################################## NETWORK #####################################

# By default, if no "bind" configuration directive is specified, Redis listens
# for connections from all the network interfaces available on the server.
# It is possible to listen to just one or multiple selected interfaces using
# the "bind" configuration directive, followed by one or more IP addresses.
#
# Examples:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
#
# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the
# internet, binding to all the interfaces is dangerous and will expose the
# instance to everybody on the internet. So by default we uncomment the
# following bind directive, that will force Redis to listen only into
# the IPv4 loopback interface address (this means Redis will be able to
# accept connections only from clients running into the same computer it
# is running).
#
# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
# JUST COMMENT THE FOLLOWING LINE.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bind 172.22.6.3

# Protected mode is a layer of security protection, in order to avoid that
# Redis instances left open on the internet are accessed and exploited.
#
# When protected mode is on and if:
#
# 1) The server is not binding explicitly to a set of addresses using the
#    "bind" directive.
# 2) No password is configured.
#
# The server only accepts connections from clients connecting from the
# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain
# sockets.
#
# By default protected mode is enabled. You should disable it only if
# you are sure you want clients from other hosts to connect to Redis
# even if no authentication is configured, nor a specific set of interfaces
# are explicitly listed using the "bind" directive.
protected-mode no

# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
port 6379

# TCP listen() backlog.
#
# In high requests-per-second environments you need an high backlog in order
# to avoid slow clients connections issues. Note that the Linux kernel
# will silently truncate it to the value of /proc/sys/net/core/somaxconn so
# make sure to raise both the value of somaxconn and tcp_max_syn_backlog
# in order to get the desired effect.
tcp-backlog 511

# Unix socket.
#
# Specify the path for the Unix socket that will be used to listen for
# incoming connections. There is no default, so Redis will not listen
# on a unix socket when not specified.
#
# unixsocket /tmp/redis.sock
# unixsocketperm 700

# Close the connection after a client is idle for N seconds (0 to disable)
timeout 0

# TCP keepalive.
#
# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence
# of communication. This is useful for two reasons:
#
# 1) Detect dead peers.
# 2) Take the connection alive from the point of view of network
#    equipment in the middle.
#
# On Linux, the specified value (in seconds) is the period used to send ACKs.
# Note that to close the connection the double of the time is needed.
# On other kernels the period depends on the kernel configuration.
#
# A reasonable value for this option is 300 seconds, which is the new
# Redis default starting with Redis 3.2.1.
tcp-keepalive 300

################################# GENERAL #####################################

# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize yes

# If you run Redis from upstart or systemd, Redis can interact with your
# supervision tree. Options:
#   supervised no      - no supervision interaction
#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode
#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
#   supervised auto    - detect upstart or systemd method based on
#                        UPSTART_JOB or NOTIFY_SOCKET environment variables
# Note: these supervision methods only signal "process is ready."
#       They do not enable continuous liveness pings back to your supervisor.
supervised no

# If a pid file is specified, Redis writes it where specified at startup
# and removes it at exit.
#
# When the server runs non daemonized, no pid file is created if none is
# specified in the configuration. When the server is daemonized, the pid file
# is used even if not specified, defaulting to "/var/run/redis.pid".
#
# Creating a pid file is best effort: if Redis is not able to create it
# nothing bad happens, the server will start and run normally.
pidfile /var/run/redis/redis-6379.pid

# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice

# Specify the log file name. Also the empty string can be used to force
# Redis to log on the standard output. Note that if you use standard
# output for logging but daemonize, logs will be sent to /dev/null
logfile ""

# To enable logging to the system logger, just set 'syslog-enabled' to yes,
# and optionally update the other syslog parameters to suit your needs.
# syslog-enabled no

# Specify the syslog identity.
# syslog-ident redis

# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
# syslog-facility local0

# Set the number of databases. The default database is DB 0, you can select
# a different one on a per-connection basis using SELECT <dbid> where
# dbid is a number between 0 and 'databases'-1
databases 16

# By default Redis shows an ASCII art logo only when started to log to the
# standard output and if the standard output is a TTY. Basically this means
# that normally a logo is displayed only in interactive sessions.
#
# However it is possible to force the pre-4.0 behavior and always show a
# ASCII art logo in startup logs by setting the following option to yes.
always-show-logo yes

################################ SNAPSHOTTING  ################################
#
# Save the DB on disk:
#
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving completely by commenting out all "save" lines.
#
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#
#   save ""

save 900 1
save 300 10
save 60 10000

# By default Redis will stop accepting writes if RDB snapshots are enabled
# (at least one save point) and the latest background save failed.
# This will make the user aware (in a hard way) that data is not persisting
# on disk properly, otherwise chances are that no one will notice and some
# disaster will happen.
#
# If the background saving process will start working again Redis will
# automatically allow writes again.
#
# However if you have setup your proper monitoring of the Redis server
# and persistence, you may want to disable this feature so that Redis will
# continue to work as usual even if there are problems with disk,
# permissions, and so forth.
stop-writes-on-bgsave-error yes

# Compress string objects using LZF when dump .rdb databases?
# For default that's set to 'yes' as it's almost always a win.
# If you want to save some CPU in the saving child set it to 'no' but
# the dataset will likely be bigger if you have compressible values or keys.
rdbcompression yes

# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.
# This makes the format more resistant to corruption but there is a performance
# hit to pay (around 10%) when saving and loading RDB files, so you can disable it
# for maximum performances.
#
# RDB files created with checksum disabled have a checksum of zero that will
# tell the loading code to skip the check.
rdbchecksum yes

# The filename where to dump the DB
dbfilename dump.rdb

# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir ./

################################# REPLICATION #################################

# Master-Replica replication. Use replicaof to make a Redis instance a copy of
# another Redis server. A few things to understand ASAP about Redis replication.
#
#   +------------------+      +---------------+
#   |      Master      | ---> |    Replica    |
#   | (receive writes) |      |  (exact copy) |
#   +------------------+      +---------------+
#
# 1) Redis replication is asynchronous, but you can configure a master to
#    stop accepting writes if it appears to be not connected with at least
#    a given number of replicas.
# 2) Redis replicas are able to perform a partial resynchronization with the
#    master if the replication link is lost for a relatively small amount of
#    time. You may want to configure the replication backlog size (see the next
#    sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a
#    network partition replicas automatically try to reconnect to masters
#    and resynchronize with them.
#
# replicaof <masterip> <masterport>

# If the master is password protected (using the "requirepass" configuration
# directive below) it is possible to tell the replica to authenticate before
# starting the replication synchronization process, otherwise the master will
# refuse the replica request.
#
# masterauth <master-password>

# When a replica loses its connection with the master, or when the replication
# is still in progress, the replica can act in two different ways:
#
# 1) if replica-serve-stale-data is set to 'yes' (the default) the replica will
#    still reply to client requests, possibly with out of date data, or the
#    data set may just be empty if this is the first synchronization.
#
# 2) if replica-serve-stale-data is set to 'no' the replica will reply with
#    an error "SYNC with master in progress" to all the kind of commands
#    but to INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG,
#    SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB,
#    COMMAND, POST, HOST: and LATENCY.
#
replica-serve-stale-data yes

# You can configure a replica instance to accept writes or not. Writing against
# a replica instance may be useful to store some ephemeral data (because data
# written on a replica will be easily deleted after resync with the master) but
# may also cause problems if clients are writing to it because of a
# misconfiguration.
#
# Since Redis 2.6 by default replicas are read-only.
#
# Note: read only replicas are not designed to be exposed to untrusted clients
# on the internet. It's just a protection layer against misuse of the instance.
# Still a read only replica exports by default all the administrative commands
# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve
# security of read only replicas using 'rename-command' to shadow all the
# administrative / dangerous commands.
replica-read-only yes

# Replication SYNC strategy: disk or socket.
#
# -------------------------------------------------------
# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY
# -------------------------------------------------------
#
# New replicas and reconnecting replicas that are not able to continue the replication
# process just receiving differences, need to do what is called a "full
# synchronization". An RDB file is transmitted from the master to the replicas.
# The transmission can happen in two different ways:
#
# 1) Disk-backed: The Redis master creates a new process that writes the RDB
#                 file on disk. Later the file is transferred by the parent
#                 process to the replicas incrementally.
# 2) Diskless: The Redis master creates a new process that directly writes the
#              RDB file to replica sockets, without touching the disk at all.
#
# With disk-backed replication, while the RDB file is generated, more replicas
# can be queued and served with the RDB file as soon as the current child producing
# the RDB file finishes its work. With diskless replication instead once
# the transfer starts, new replicas arriving will be queued and a new transfer
# will start when the current one terminates.
#
# When diskless replication is used, the master waits a configurable amount of
# time (in seconds) before starting the transfer in the hope that multiple replicas
# will arrive and the transfer can be parallelized.
#
# With slow disks and fast (large bandwidth) networks, diskless replication
# works better.
repl-diskless-sync no

# When diskless replication is enabled, it is possible to configure the delay
# the server waits in order to spawn the child that transfers the RDB via socket
# to the replicas.
#
# This is important since once the transfer starts, it is not possible to serve
# new replicas arriving, that will be queued for the next RDB transfer, so the server
# waits a delay in order to let more replicas arrive.
#
# The delay is specified in seconds, and by default is 5 seconds. To disable
# it entirely just set it to 0 seconds and the transfer will start ASAP.
repl-diskless-sync-delay 5

# Replicas send PINGs to server in a predefined interval. It's possible to change
# this interval with the repl_ping_replica_period option. The default value is 10
# seconds.
#
# repl-ping-replica-period 10

# The following option sets the replication timeout for:
#
# 1) Bulk transfer I/O during SYNC, from the point of view of replica.
# 2) Master timeout from the point of view of replicas (data, pings).
# 3) Replica timeout from the point of view of masters (REPLCONF ACK pings).
#
# It is important to make sure that this value is greater than the value
# specified for repl-ping-replica-period otherwise a timeout will be detected
# every time there is low traffic between the master and the replica.
#
# repl-timeout 60

# Disable TCP_NODELAY on the replica socket after SYNC?
#
# If you select "yes" Redis will use a smaller number of TCP packets and
# less bandwidth to send data to replicas. But this can add a delay for
# the data to appear on the replica side, up to 40 milliseconds with
# Linux kernels using a default configuration.
#
# If you select "no" the delay for data to appear on the replica side will
# be reduced but more bandwidth will be used for replication.
#
# By default we optimize for low latency, but in very high traffic conditions
# or when the master and replicas are many hops away, turning this to "yes" may
# be a good idea.
repl-disable-tcp-nodelay no

# Set the replication backlog size. The backlog is a buffer that accumulates
# replica data when replicas are disconnected for some time, so that when a replica
# wants to reconnect again, often a full resync is not needed, but a partial
# resync is enough, just passing the portion of data the replica missed while
# disconnected.
#
# The bigger the replication backlog, the longer the time the replica can be
# disconnected and later be able to perform a partial resynchronization.
#
# The backlog is only allocated once there is at least a replica connected.
#
# repl-backlog-size 1mb

# After a master has no longer connected replicas for some time, the backlog
# will be freed. The following option configures the amount of seconds that
# need to elapse, starting from the time the last replica disconnected, for
# the backlog buffer to be freed.
#
# Note that replicas never free the backlog for timeout, since they may be
# promoted to masters later, and should be able to correctly "partially
# resynchronize" with the replicas: hence they should always accumulate backlog.
#
# A value of 0 means to never release the backlog.
#
# repl-backlog-ttl 3600

# The replica priority is an integer number published by Redis in the INFO output.
# It is used by Redis Sentinel in order to select a replica to promote into a
# master if the master is no longer working correctly.
#
# A replica with a low priority number is considered better for promotion, so
# for instance if there are three replicas with priority 10, 100, 25 Sentinel will
# pick the one with priority 10, that is the lowest.
#
# However a special priority of 0 marks the replica as not able to perform the
# role of master, so a replica with priority of 0 will never be selected by
# Redis Sentinel for promotion.
#
# By default the priority is 100.
replica-priority 100

# It is possible for a master to stop accepting writes if there are less than
# N replicas connected, having a lag less or equal than M seconds.
#
# The N replicas need to be in "online" state.
#
# The lag in seconds, that must be <= the specified value, is calculated from
# the last ping received from the replica, that is usually sent every second.
#
# This option does not GUARANTEE that N replicas will accept the write, but
# will limit the window of exposure for lost writes in case not enough replicas
# are available, to the specified number of seconds.
#
# For example to require at least 3 replicas with a lag <= 10 seconds use:
#
# min-replicas-to-write 3
# min-replicas-max-lag 10
#
# Setting one or the other to 0 disables the feature.
#
# By default min-replicas-to-write is set to 0 (feature disabled) and
# min-replicas-max-lag is set to 10.

# A Redis master is able to list the address and port of the attached
# replicas in different ways. For example the "INFO replication" section
# offers this information, which is used, among other tools, by
# Redis Sentinel in order to discover replica instances.
# Another place where this info is available is in the output of the
# "ROLE" command of a master.
#
# The listed IP and address normally reported by a replica is obtained
# in the following way:
#
#   IP: The address is auto detected by checking the peer address
#   of the socket used by the replica to connect with the master.
#
#   Port: The port is communicated by the replica during the replication
#   handshake, and is normally the port that the replica is using to
#   listen for connections.
#
# However when port forwarding or Network Address Translation (NAT) is
# used, the replica may be actually reachable via different IP and port
# pairs. The following two options can be used by a replica in order to
# report to its master a specific set of IP and port, so that both INFO
# and ROLE will report those values.
#
# There is no need to use both the options if you need to override just
# the port or the IP address.
#
# replica-announce-ip 5.5.5.5
# replica-announce-port 1234

################################## SECURITY ###################################

# Require clients to issue AUTH <PASSWORD> before processing any other
# commands.  This might be useful in environments in which you do not trust
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
#:q
# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
#
# requirepass

# Command renaming.
#
# It is possible to change the name of dangerous commands in a shared
# environment. For instance the CONFIG command may be renamed into something
# hard to guess so that it will still be available for internal-use tools
# but not available for general clients.
#
# Example:
#
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#
# It is also possible to completely kill a command by renaming it into
# an empty string:
#
# rename-command CONFIG ""
#
# Please note that changing the name of commands that are logged into the
# AOF file or transmitted to replicas may cause problems.

################################### CLIENTS ####################################

# Set the max number of connected clients at the same time. By default
# this limit is set to 10000 clients, however if the Redis server is not
# able to configure the process file limit to allow for the specified limit
# the max number of allowed clients is set to the current file limit
# minus 32 (as Redis reserves a few file descriptors for internal uses).
#
# Once the limit is reached Redis will close all the new connections sending
# an error 'max number of clients reached'.
#
# maxclients 10000

############################## MEMORY MANAGEMENT ################################

# Set a memory usage limit to the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU or LFU cache, or to
# set a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have replicas attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the replicas are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of replicas is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have replicas attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for replica
# output buffers (but this is not needed if the policy is 'noeviction').
#
# maxmemory <bytes>

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
#
# LRU means Least Recently Used
# LFU means Least Frequently Used
#
# Both LRU, LFU and volatile-ttl are implemented using approximated
# randomized algorithms.
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction

# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated
# algorithms (in order to save memory), so you can tune it for speed or
# accuracy. For default Redis will check five keys and pick the one that was
# used less recently, you can change the sample size using the following
# configuration directive.
#
# The default of 5 produces good enough results. 10 Approximates very closely
# true LRU but costs more CPU. 3 is faster but not very accurate.
#
# maxmemory-samples 5

# Starting from Redis 5, by default a replica will ignore its maxmemory setting
# (unless it is promoted to master after a failover or manually). It means
# that the eviction of keys will be just handled by the master, sending the
# DEL commands to the replica as keys evict in the master side.
#
# This behavior ensures that masters and replicas stay consistent, and is usually
# what you want, however if your replica is writable, or you want the replica to have
# a different memory setting, and you are sure all the writes performed to the
# replica are idempotent, then you may change this default (but be sure to understand
# what you are doing).
#
# Note that since the replica by default does not evict, it may end using more
# memory than the one set via maxmemory (there are certain buffers that may
# be larger on the replica, or data structures may sometimes take more memory and so
# forth). So make sure you monitor your replicas and make sure they have enough
# memory to never hit a real out-of-memory condition before the master hits
# the configured maxmemory setting.
#
# replica-ignore-maxmemory yes

############################# LAZY FREEING ####################################

# Redis has two primitives to delete keys. One is called DEL and is a blocking
# deletion of the object. It means that the server stops processing new commands
# in order to reclaim all the memory associated with an object in a synchronous
# way. If the key deleted is associated with a small object, the time needed
# in order to execute the DEL command is very small and comparable to most other
# O(1) or O(log_N) commands in Redis. However if the key is associated with an
# aggregated value containing millions of elements, the server can block for
# a long time (even seconds) in order to complete the operation.
#
# For the above reasons Redis also offers non blocking deletion primitives
# such as UNLINK (non blocking DEL) and the ASYNC option of FLUSHALL and
# FLUSHDB commands, in order to reclaim memory in background. Those commands
# are executed in constant time. Another thread will incrementally free the
# object in the background as fast as possible.
#
# DEL, UNLINK and ASYNC option of FLUSHALL and FLUSHDB are user-controlled.
# It's up to the design of the application to understand when it is a good
# idea to use one or the other. However the Redis server sometimes has to
# delete keys or flush the whole database as a side effect of other operations.
# Specifically Redis deletes objects independently of a user call in the
# following scenarios:
#
# 1) On eviction, because of the maxmemory and maxmemory policy configurations,
#    in order to make room for new data, without going over the specified
#    memory limit.
# 2) Because of expire: when a key with an associated time to live (see the
#    EXPIRE command) must be deleted from memory.
# 3) Because of a side effect of a command that stores data on a key that may
#    already exist. For example the RENAME command may delete the old key
#    content when it is replaced with another one. Similarly SUNIONSTORE
#    or SORT with STORE option may delete existing keys. The SET command
#    itself removes any old content of the specified key in order to replace
#    it with the specified string.
# 4) During replication, when a replica performs a full resynchronization with
#    its master, the content of the whole database is removed in order to
#    load the RDB file just transferred.
#
# In all the above cases the default is to delete objects in a blocking way,
# like if DEL was called. However you can configure each case specifically
# in order to instead release memory in a non-blocking way like if UNLINK
# was called, using the following configuration directives:

lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no

############################## APPEND ONLY MODE ###############################

# By default Redis asynchronously dumps the dataset on disk. This mode is
# good enough in many applications, but an issue with the Redis process or
# a power outage may result into a few minutes of writes lost (depending on
# the configured save points).
#
# The Append Only File is an alternative persistence mode that provides
# much better durability. For instance using the default data fsync policy
# (see later in the config file) Redis can lose just one second of writes in a
# dramatic event like a server power outage, or a single write if something
# wrong with the Redis process itself happens, but the operating system is
# still running correctly.
#
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
#
# Please check http://redis.io/topics/persistence for more information.

appendonly yes

# The name of the append only file (default: "appendonly.aof")

appendfilename "appendonly.aof"

# The fsync() call tells the Operating System to actually write data on disk
# instead of waiting for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.
#
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log. Slow, Safest.
# everysec: fsync only one time every second. Compromise.
#
# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use "always" that's very slow but a bit safer than
# everysec.
#
# More details please check the following article:
# http://antirez.com/post/redis-persistence-demystified.html
#
# If unsure, use "everysec".

# appendfsync always
appendfsync everysec
# appendfsync no

# When the AOF fsync policy is set to always or everysec, and a background
# saving process (a background save or AOF log background rewriting) is
# performing a lot of I/O against the disk, in some Linux configurations
# Redis may block too long on the fsync() call. Note that there is no fix for
# this currently, as even performing fsync in a different thread will block
# our synchronous write(2) call.
#
# In order to mitigate this problem it's possible to use the following option
# that will prevent fsync() from being called in the main process while a
# BGSAVE or BGREWRITEAOF is in progress.
#
# This means that while another child is saving, the durability of Redis is
# the same as "appendfsync none". In practical terms, this means that it is
# possible to lose up to 30 seconds of log in the worst scenario (with the
# default Linux settings).
#
# If you have latency problems turn this to "yes". Otherwise leave it as
# "no" that is the safest pick from the point of view of durability.

no-appendfsync-on-rewrite no

# Automatic rewrite of the append only file.
# Redis is able to automatically rewrite the log file implicitly calling
# BGREWRITEAOF when the AOF log size grows by the specified percentage.
#
# This is how it works: Redis remembers the size of the AOF file after the
# latest rewrite (if no rewrite has happened since the restart, the size of
# the AOF at startup is used).
#
# This base size is compared to the current size. If the current size is
# bigger than the specified percentage, the rewrite is triggered. Also
# you need to specify a minimal size for the AOF file to be rewritten, this
# is useful to avoid rewriting the AOF file even if the percentage increase
# is reached but it is still pretty small.
#
# Specify a percentage of zero in order to disable the automatic AOF
# rewrite feature.

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# An AOF file may be found to be truncated at the end during the Redis
# startup process, when the AOF data gets loaded back into memory.
# This may happen when the system where Redis is running
# crashes, especially when an ext4 filesystem is mounted without the
# data=ordered option (however this can't happen when Redis itself
# crashes or aborts but the operating system still works correctly).
#
# Redis can either exit with an error when this happens, or load as much
# data as possible (the default now) and start if the AOF file is found
# to be truncated at the end. The following option controls this behavior.
#
# If aof-load-truncated is set to yes, a truncated AOF file is loaded and
# the Redis server starts emitting a log to inform the user of the event.
# Otherwise if the option is set to no, the server aborts with an error
# and refuses to start. When the option is set to no, the user requires
# to fix the AOF file using the "redis-check-aof" utility before to restart
# the server.
#
# Note that if the AOF file will be found to be corrupted in the middle
# the server will still exit with an error. This option only applies when
# Redis will try to read more data from the AOF file but not enough bytes
# will be found.
aof-load-truncated yes

# When rewriting the AOF file, Redis is able to use an RDB preamble in the
# AOF file for faster rewrites and recoveries. When this option is turned
# on the rewritten AOF file is composed of two different stanzas:
#
#   [RDB file][AOF tail]
#
# When loading Redis recognizes that the AOF file starts with the "REDIS"
# string and loads the prefixed RDB file, and continues loading the AOF
# tail.
aof-use-rdb-preamble yes

################################ LUA SCRIPTING  ###############################

# Max execution time of a Lua script in milliseconds.
#
# If the maximum execution time is reached Redis will log that a script is
# still in execution after the maximum allowed time and will start to
# reply to queries with an error.
#
# When a long running script exceeds the maximum execution time only the
# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be
# used to stop a script that did not yet called write commands. The second
# is the only way to shut down the server in the case a write command was
# already issued by the script but the user doesn't want to wait for the natural
# termination of the script.
#
# Set it to 0 or a negative value for unlimited execution without warnings.
lua-time-limit 5000

################################ REDIS CLUSTER  ###############################
#
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however
# in order to mark it as "mature" we need to wait for a non trivial percentage
# of users to deploy it in production.
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#
# Normal Redis instances can't be part of a Redis Cluster; only nodes that are
# started as cluster nodes can. In order to start a Redis instance as a
# cluster node enable the cluster support uncommenting the following:
#
# cluster-enabled yes

# Every cluster node has a cluster configuration file. This file is not
# intended to be edited by hand. It is created and updated by Redis nodes.
# Every Redis Cluster node requires a different cluster configuration file.
# Make sure that instances running in the same system do not have
# overlapping cluster configuration file names.
#
# cluster-config-file nodes-6379.conf

# Cluster node timeout is the amount of milliseconds a node must be unreachable
# for it to be considered in failure state.
# Most other internal time limits are multiple of the node timeout.
#
# cluster-node-timeout 15000

# A replica of a failing master will avoid to start a failover if its data
# looks too old.
#
# There is no simple way for a replica to actually have an exact measure of
# its "data age", so the following two checks are performed:
#
# 1) If there are multiple replicas able to failover, they exchange messages
#    in order to try to give an advantage to the replica with the best
#    replication offset (more data from the master processed).
#    Replicas will try to get their rank by offset, and apply to the start
#    of the failover a delay proportional to their rank.
#
# 2) Every single replica computes the time of the last interaction with
#    its master. This can be the last ping or command received (if the master
#    is still in the "connected" state), or the time that elapsed since the
#    disconnection with the master (if the replication link is currently down).
#    If the last interaction is too old, the replica will not try to failover
#    at all.
#
# The point "2" can be tuned by user. Specifically a replica will not perform
# the failover if, since the last interaction with the master, the time
# elapsed is greater than:
#
#   (node-timeout * replica-validity-factor) + repl-ping-replica-period
#
# So for example if node-timeout is 30 seconds, and the replica-validity-factor
# is 10, and assuming a default repl-ping-replica-period of 10 seconds, the
# replica will not try to failover if it was not able to talk with the master
# for longer than 310 seconds.
#
# A large replica-validity-factor may allow replicas with too old data to failover
# a master, while a too small value may prevent the cluster from being able to
# elect a replica at all.
#
# For maximum availability, it is possible to set the replica-validity-factor
# to a value of 0, which means, that replicas will always try to failover the
# master regardless of the last time they interacted with the master.
# (However they'll always try to apply a delay proportional to their
# offset rank).
#
# Zero is the only value able to guarantee that when all the partitions heal
# the cluster will always be able to continue.
#
# cluster-replica-validity-factor 10

# Cluster replicas are able to migrate to orphaned masters, that are masters
# that are left without working replicas. This improves the cluster ability
# to resist to failures as otherwise an orphaned master can't be failed over
# in case of failure if it has no working replicas.
#
# Replicas migrate to orphaned masters only if there are still at least a
# given number of other working replicas for their old master. This number
# is the "migration barrier". A migration barrier of 1 means that a replica
# will migrate only if there is at least 1 other working replica for its master
# and so forth. It usually reflects the number of replicas you want for every
# master in your cluster.
#
# Default is 1 (replicas migrate only if their masters remain with at least
# one replica). To disable migration just set it to a very large value.
# A value of 0 can be set but is useful only for debugging and dangerous
# in production.
#
# cluster-migration-barrier 1

# By default Redis Cluster nodes stop accepting queries if they detect there
# is at least an hash slot uncovered (no available node is serving it).
# This way if the cluster is partially down (for example a range of hash slots
# are no longer covered) all the cluster becomes, eventually, unavailable.
# It automatically returns available as soon as all the slots are covered again.
#
# However sometimes you want the subset of the cluster which is working,
# to continue to accept queries for the part of the key space that is still
# covered. In order to do so, just set the cluster-require-full-coverage
# option to no.
#
# cluster-require-full-coverage yes

# This option, when set to yes, prevents replicas from trying to failover its
# master during master failures. However the master can still perform a
# manual failover, if forced to do so.
#
# This is useful in different scenarios, especially in the case of multiple
# data center operations, where we want one side to never be promoted if not
# in the case of a total DC failure.
#
# cluster-replica-no-failover no

# In order to setup your cluster make sure to read the documentation
# available at http://redis.io web site.

########################## CLUSTER DOCKER/NAT support  ########################

# In certain deployments, Redis Cluster nodes address discovery fails, because
# addresses are NAT-ted or because ports are forwarded (the typical case is
# Docker and other containers).
#
# In order to make Redis Cluster working in such environments, a static
# configuration where each node knows its public address is needed. The
# following two options are used for this scope, and are:
#
# * cluster-announce-ip
# * cluster-announce-port
# * cluster-announce-bus-port
#
# Each instruct the node about its address, client port, and cluster message
# bus port. The information is then published in the header of the bus packets
# so that other nodes will be able to correctly map the address of the node
# publishing the information.
#
# If the above options are not used, the normal Redis Cluster auto-detection
# will be used instead.
#
# Note that when remapped, the bus port may not be at the fixed offset of
# clients port + 10000, so you can specify any port and bus-port depending
# on how they get remapped. If the bus-port is not set, a fixed offset of
# 10000 will be used as usually.
#
# Example:
#
# cluster-announce-ip 10.1.1.5
# cluster-announce-port 6379
# cluster-announce-bus-port 6380

################################## SLOW LOG ###################################

# The Redis Slow Log is a system to log queries that exceeded a specified
# execution time. The execution time does not include the I/O operations
# like talking with the client, sending the reply and so forth,
# but just the time needed to actually execute the command (this is the only
# stage of command execution where the thread is blocked and can not serve
# other requests in the meantime).
#
# You can configure the slow log with two parameters: one tells Redis
# what is the execution time, in microseconds, to exceed in order for the
# command to get logged, and the other parameter is the length of the
# slow log. When a new command is logged the oldest one is removed from the
# queue of logged commands.

# The following time is expressed in microseconds, so 1000000 is equivalent
# to one second. Note that a negative number disables the slow log, while
# a value of zero forces the logging of every command.
slowlog-log-slower-than 10000

# There is no limit to this length. Just be aware that it will consume memory.
# You can reclaim memory used by the slow log with SLOWLOG RESET.
slowlog-max-len 128

################################ LATENCY MONITOR ##############################

# The Redis latency monitoring subsystem samples different operations
# at runtime in order to collect data related to possible sources of
# latency of a Redis instance.
#
# Via the LATENCY command this information is available to the user that can
# print graphs and obtain reports.
#
# The system only logs operations that were performed in a time equal or
# greater than the amount of milliseconds specified via the
# latency-monitor-threshold configuration directive. When its value is set
# to zero, the latency monitor is turned off.
#
# By default latency monitoring is disabled since it is mostly not needed
# if you don't have latency issues, and collecting data has a performance
# impact, that while very small, can be measured under big load. Latency
# monitoring can easily be enabled at runtime using the command
# "CONFIG SET latency-monitor-threshold <milliseconds>" if needed.
latency-monitor-threshold 0

############################# EVENT NOTIFICATION ##############################

# Redis can notify Pub/Sub clients about events happening in the key space.
# This feature is documented at http://redis.io/topics/notifications
#
# For instance if keyspace events notification is enabled, and a client
# performs a DEL operation on key "foo" stored in the Database 0, two
# messages will be published via Pub/Sub:
#
# PUBLISH __keyspace@0__:foo del
# PUBLISH __keyevent@0__:del foo
#
# It is possible to select the events that Redis will notify among a set
# of classes. Every class is identified by a single character:
#
#  K     Keyspace events, published with __keyspace@<db>__ prefix.
#  E     Keyevent events, published with __keyevent@<db>__ prefix.
#  g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
#  $     String commands
#  l     List commands
#  s     Set commands
#  h     Hash commands
#  z     Sorted set commands
#  x     Expired events (events generated every time a key expires)
#  e     Evicted events (events generated when a key is evicted for maxmemory)
#  A     Alias for g$lshzxe, so that the "AKE" string means all the events.
#
#  The "notify-keyspace-events" takes as argument a string that is composed
#  of zero or multiple characters. The empty string means that notifications
#  are disabled.
#
#  Example: to enable list and generic events, from the point of view of the
#           event name, use:
#
#  notify-keyspace-events Elg
#
#  Example 2: to get the stream of the expired keys subscribing to channel
#             name __keyevent@0__:expired use:
#
#  notify-keyspace-events Ex
#
#  By default all notifications are disabled because most users don't need
#  this feature and the feature has some overhead. Note that if you don't
#  specify at least one of K or E, no events will be delivered.
notify-keyspace-events ""

############################### ADVANCED CONFIG ###############################

# Hashes are encoded using a memory efficient data structure when they have a
# small number of entries, and the biggest entry does not exceed a given
# threshold. These thresholds can be configured using the following directives.
hash-max-ziplist-entries 512
hash-max-ziplist-value 64

# Lists are also encoded in a special way to save a lot of space.
# The number of entries allowed per internal list node can be specified
# as a fixed maximum size or a maximum number of elements.
# For a fixed maximum size, use -5 through -1, meaning:
# -5: max size: 64 Kb  <-- not recommended for normal workloads
# -4: max size: 32 Kb  <-- not recommended
# -3: max size: 16 Kb  <-- probably not recommended
# -2: max size: 8 Kb   <-- good
# -1: max size: 4 Kb   <-- good
# Positive numbers mean store up to _exactly_ that number of elements
# per list node.
# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size),
# but if your use case is unique, adjust the settings as necessary.
list-max-ziplist-size -2

# Lists may also be compressed.
# Compress depth is the number of quicklist ziplist nodes from *each* side of
# the list to *exclude* from compression.  The head and tail of the list
# are always uncompressed for fast push/pop operations.  Settings are:
# 0: disable all list compression
# 1: depth 1 means "don't start compressing until after 1 node into the list,
#    going from either the head or tail"
#    So: [head]->node->node->...->node->[tail]
#    [head], [tail] will always be uncompressed; inner nodes will compress.
# 2: [head]->[next]->node->node->...->node->[prev]->[tail]
#    2 here means: don't compress head or head->next or tail->prev or tail,
#    but compress all nodes between them.
# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail]
# etc.
list-compress-depth 0

# Sets have a special encoding in just one case: when a set is composed
# of just strings that happen to be integers in radix 10 in the range
# of 64 bit signed integers.
# The following configuration setting sets the limit in the size of the
# set in order to use this special memory saving encoding.
set-max-intset-entries 512

# Similarly to hashes and lists, sorted sets are also specially encoded in
# order to save a lot of space. This encoding is only used when the length and
# elements of a sorted set are below the following limits:
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

# HyperLogLog sparse representation bytes limit. The limit includes the
# 16 bytes header. When an HyperLogLog using the sparse representation crosses
# this limit, it is converted into the dense representation.
#
# A value greater than 16000 is totally useless, since at that point the
# dense representation is more memory efficient.
#
# The suggested value is ~ 3000 in order to have the benefits of
# the space efficient encoding without slowing down too much PFADD,
# which is O(N) with the sparse encoding. The value can be raised to
# ~ 10000 when CPU is not a concern, but space is, and the data set is
# composed of many HyperLogLogs with cardinality in the 0 - 15000 range.
hll-sparse-max-bytes 3000

# Streams macro node max size / items. The stream data structure is a radix
# tree of big nodes that encode multiple items inside. Using this configuration
# it is possible to configure how big a single node can be in bytes, and the
# maximum number of items it may contain before switching to a new node when
# appending new stream entries. If any of the following settings are set to
# zero, the limit is ignored, so for instance it is possible to set just a
# max entires limit by setting max-bytes to 0 and max-entries to the desired
# value.
stream-node-max-bytes 4096
stream-node-max-entries 100

# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in
# order to help rehashing the main Redis hash table (the one mapping top-level
# keys to values). The hash table implementation Redis uses (see dict.c)
# performs a lazy rehashing: the more operation you run into a hash table
# that is rehashing, the more rehashing "steps" are performed, so if the
# server is idle the rehashing is never complete and some more memory is used
# by the hash table.
#
# The default is to use this millisecond 10 times every second in order to
# actively rehash the main dictionaries, freeing memory when possible.
#
# If unsure:
# use "activerehashing no" if you have hard latency requirements and it is
# not a good thing in your environment that Redis can reply from time to time
# to queries with 2 milliseconds delay.
#
# use "activerehashing yes" if you don't have such hard requirements but
# want to free memory asap when possible.
activerehashing yes

# The client output buffer limits can be used to force disconnection of clients
# that are not reading data from the server fast enough for some reason (a
# common reason is that a Pub/Sub client can't consume messages as fast as the
# publisher can produce them).
#
# The limit can be set differently for the three different classes of clients:
#
# normal -> normal clients including MONITOR clients
# replica  -> replica clients
# pubsub -> clients subscribed to at least one pubsub channel or pattern
#
# The syntax of every client-output-buffer-limit directive is the following:
#
# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>
#
# A client is immediately disconnected once the hard limit is reached, or if
# the soft limit is reached and remains reached for the specified number of
# seconds (continuously).
# So for instance if the hard limit is 32 megabytes and the soft limit is
# 16 megabytes / 10 seconds, the client will get disconnected immediately
# if the size of the output buffers reach 32 megabytes, but will also get
# disconnected if the client reaches 16 megabytes and continuously overcomes
# the limit for 10 seconds.
#
# By default normal clients are not limited because they don't receive data
# without asking (in a push way), but just after a request, so only
# asynchronous clients may create a scenario where data is requested faster
# than it can read.
#
# Instead there is a default limit for pubsub and replica clients, since
# subscribers and replicas receive data in a push fashion.
#
# Both the hard or the soft limit can be disabled by setting them to zero.
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

# Client query buffers accumulate new commands. They are limited to a fixed
# amount by default in order to avoid that a protocol desynchronization (for
# instance due to a bug in the client) will lead to unbound memory usage in
# the query buffer. However you can configure it here if you have very special
# needs, such us huge multi/exec requests or alike.
#
# client-query-buffer-limit 1gb

# In the Redis protocol, bulk requests, that are, elements representing single
# strings, are normally limited ot 512 mb. However you can change this limit
# here.
#
# proto-max-bulk-len 512mb

# Redis calls an internal function to perform many background tasks, like
# closing connections of clients in timeout, purging expired keys that are
# never requested, and so forth.
#
# Not all tasks are performed with the same frequency, but Redis checks for
# tasks to perform according to the specified "hz" value.
#
# By default "hz" is set to 10. Raising the value will use more CPU when
# Redis is idle, but at the same time will make Redis more responsive when
# there are many keys expiring at the same time, and timeouts may be
# handled with more precision.
#
# The range is between 1 and 500, however a value over 100 is usually not
# a good idea. Most users should use the default of 10 and raise this up to
# 100 only in environments where very low latency is required.
hz 10

# Normally it is useful to have an HZ value which is proportional to the
# number of clients connected. This is useful in order, for instance, to
# avoid too many clients are processed for each background task invocation
# in order to avoid latency spikes.
#
# Since the default HZ value by default is conservatively set to 10, Redis
# offers, and enables by default, the ability to use an adaptive HZ value
# which will temporary raise when there are many connected clients.
#
# When dynamic HZ is enabled, the actual configured HZ will be used as
# as a baseline, but multiples of the configured HZ value will be actually
# used as needed once more clients are connected. In this way an idle
# instance will use very little CPU time while a busy instance will be
# more responsive.
dynamic-hz yes

# When a child rewrites the AOF file, if the following option is enabled
# the file will be fsync-ed every 32 MB of data generated. This is useful
# in order to commit the file to the disk more incrementally and avoid
# big latency spikes.
aof-rewrite-incremental-fsync yes

# When redis saves RDB file, if the following option is enabled
# the file will be fsync-ed every 32 MB of data generated. This is useful
# in order to commit the file to the disk more incrementally and avoid
# big latency spikes.
rdb-save-incremental-fsync yes

# Redis LFU eviction (see maxmemory setting) can be tuned. However it is a good
# idea to start with the default settings and only change them after investigating
# how to improve the performances and how the keys LFU change over time, which
# is possible to inspect via the OBJECT FREQ command.
#
# There are two tunable parameters in the Redis LFU implementation: the
# counter logarithm factor and the counter decay time. It is important to
# understand what the two parameters mean before changing them.
#
# The LFU counter is just 8 bits per key, it's maximum value is 255, so Redis
# uses a probabilistic increment with logarithmic behavior. Given the value
# of the old counter, when a key is accessed, the counter is incremented in
# this way:
#
# 1. A random number R between 0 and 1 is extracted.
# 2. A probability P is calculated as 1/(old_value*lfu_log_factor+1).
# 3. The counter is incremented only if R < P.
#
# The default lfu-log-factor is 10. This is a table of how the frequency
# counter changes with a different number of accesses with different
# logarithmic factors:
#
# +--------+------------+------------+------------+------------+------------+
# | factor | 100 hits   | 1000 hits  | 100K hits  | 1M hits    | 10M hits   |
# +--------+------------+------------+------------+------------+------------+
# | 0      | 104        | 255        | 255        | 255        | 255        |
# +--------+------------+------------+------------+------------+------------+
# | 1      | 18         | 49         | 255        | 255        | 255        |
# +--------+------------+------------+------------+------------+------------+
# | 10     | 10         | 18         | 142        | 255        | 255        |
# +--------+------------+------------+------------+------------+------------+
# | 100    | 8          | 11         | 49         | 143        | 255        |
# +--------+------------+------------+------------+------------+------------+
#
# NOTE: The above table was obtained by running the following commands:
#
#   redis-benchmark -n 1000000 incr foo
#   redis-cli object freq foo
#
# NOTE 2: The counter initial value is 5 in order to give new objects a chance
# to accumulate hits.
#
# The counter decay time is the time, in minutes, that must elapse in order
# for the key counter to be divided by two (or decremented if it has a value
# less <= 10).
#
# The default value for the lfu-decay-time is 1. A Special value of 0 means to
# decay the counter every time it happens to be scanned.
#
# lfu-log-factor 10
# lfu-decay-time 1

########################### ACTIVE DEFRAGMENTATION #######################
#
# WARNING THIS FEATURE IS EXPERIMENTAL. However it was stress tested
# even in production and manually tested by multiple engineers for some
# time.
#
# What is active defragmentation?
# -------------------------------
#
# Active (online) defragmentation allows a Redis server to compact the
# spaces left between small allocations and deallocations of data in memory,
# thus allowing to reclaim back memory.
#
# Fragmentation is a natural process that happens with every allocator (but
# less so with Jemalloc, fortunately) and certain workloads. Normally a server
# restart is needed in order to lower the fragmentation, or at least to flush
# away all the data and create it again. However thanks to this feature
# implemented by Oran Agra for Redis 4.0 this process can happen at runtime
# in an "hot" way, while the server is running.
#
# Basically when the fragmentation is over a certain level (see the
# configuration options below) Redis will start to create new copies of the
# values in contiguous memory regions by exploiting certain specific Jemalloc
# features (in order to understand if an allocation is causing fragmentation
# and to allocate it in a better place), and at the same time, will release the
# old copies of the data. This process, repeated incrementally for all the keys
# will cause the fragmentation to drop back to normal values.
#
# Important things to understand:
#
# 1. This feature is disabled by default, and only works if you compiled Redis
#    to use the copy of Jemalloc we ship with the source code of Redis.
#    This is the default with Linux builds.
#
# 2. You never need to enable this feature if you don't have fragmentation
#    issues.
#
# 3. Once you experience fragmentation, you can enable this feature when
#    needed with the command "CONFIG SET activedefrag yes".
#
# The configuration parameters are able to fine tune the behavior of the
# defragmentation process. If you are not sure about what they mean it is
# a good idea to leave the defaults untouched.

# Enabled active defragmentation
# activedefrag yes

# Minimum amount of fragmentation waste to start active defrag
# active-defrag-ignore-bytes 100mb

# Minimum percentage of fragmentation to start active defrag
# active-defrag-threshold-lower 10

# Maximum percentage of fragmentation at which we use maximum effort
# active-defrag-threshold-upper 100

# Minimal effort for defrag in CPU percentage
# active-defrag-cycle-min 5

# Maximal effort for defrag in CPU percentage
# active-defrag-cycle-max 75

# Maximum number of set/hash/zset/list fields that will be processed from
# the main dictionary scan
# active-defrag-max-scan-fields 1000



================================================
FILE: codes/linux/soft/config/redis/redis.service
================================================
[Unit]
Description=Redis
After=network.target

[Service]
Type=forking
PIDFile=/var/run/redis/redis-6379.pid
ExecStart=/usr/local/bin/redis-server /usr/local/redis/redis.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target


================================================
FILE: codes/linux/soft/config/settings-aliyun.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>

<settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://maven.apache.org/SETTINGS/1.0.0"
	xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

	<!-- 使用 aliyun maven 仓库加速下载 -->
	<mirrors>
		<mirror>
			<id>aliyun</id>
			<name>Aliyun</name>
			<url>http://maven.aliyun.com/nexus/content/groups/public</url>
			<mirrorOf>central</mirrorOf>
		</mirror>
		<mirror>
			<id>repo2</id>
			<name>Mirror from Maven Repo2</name>
			<url>http://repo2.maven.org/maven2/</url>
			<mirrorOf>central</mirrorOf>
		</mirror>
	</mirrors>
</settings>


================================================
FILE: codes/linux/soft/docker-install.sh
================================================
#!/usr/bin/env bash

###################################################################################
# 控制台颜色
BLACK="\033[1;30m"
RED="\033[1;31m"
GREEN="\033[1;32m"
YELLOW="\033[1;33m"
BLUE="\033[1;34m"
PURPLE="\033[1;35m"
CYAN="\033[1;36m"
RESET="$(tput sgr0)"
###################################################################################

printf "${BLUE}"
cat << EOF

###################################################################################
# 安装 Docker 脚本
# 适用于所有 linux 发行版本。
# @author: Zhang Peng
###################################################################################

EOF
printf "${RESET}"

printf "${GREEN}>>>>>>>> install docker begin.${RESET}\n"
# uninstall old version docker
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

# install required libs
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# add docker yum repo
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo yum makecache fast
# install docker
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
docker version
printf "${GREEN}<<<<<<<< install docker end.${RESET}\n"

printf "${GREEN}>>>>>>>> replace chinese docker mirror registry${RESET}\n"
if [[ -f "/etc/docker/daemon.json" ]]; then
    mv /etc/docker/daemon.json /etc/docker/daemon.json.bak
else
    mkdir -p /etc/docker
fi
touch /etc/docker/daemon.json
cat >> /etc/docker/daemon.json << EOF
{
  "registry-mirrors": ["https://hub-mirror.c.163.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker


================================================
FILE: codes/linux/soft/elk/boot-elk.sh
================================================
#!/usr/bin/env bash

# 检查脚本输入参数
checkInput() {
	if [ "${app}" == "" ] || [ "${oper}" == "" ]; then
		echo "请输入脚本参数:name"
		echo "    app: 要启动的进程关键字(必填)。可选值:elasticsearch|logstash|kibana|filebeat"
		echo "    oper: 执行操作(必填)。可选值:start|stop"
		echo "例:./boot-elk.sh logstash start"
		exit 0
	fi

	if [ "${app}" != "elasticsearch" ] && [ "${app}" != "logstash" ] && [ "${app}" != "kibana" ] && [ "${app}" != "filebeat" ]; then
		echo "name 输入错误"
		echo "可选值:elasticsearch|logstash|kibana|filebeat"
		exit 0
	fi
}

# 检查文件是否存在,不存在则退出脚本
checkFileExist() {
	if [ ! -f "$1" ]
	then
		echo "关键文件 $1 找不到,脚本执行结束"
		exit 0
	fi
}

startup() {
	if [ "${app}" == "elasticsearch" ]; then
		checkFileExist ${ELASTICSEARCH_BIN_PATH}/elasticsearch
		nohup sh ${ELASTICSEARCH_BIN_PATH}/elasticsearch >> ${ELASTICSEARCH_BIN_PATH}/nohup.out 2>&1 &
	elif [ "${app}" == "logstash" ]; then
		checkFileExist ${LOGSTASH_BIN_PATH}/logstash
		nohup sh ${LOGSTASH_BIN_PATH}/logstash -f ${LOGSTASH_BIN_PATH}/logstash.conf >> ${LOGSTASH_BIN_PATH}/nohup.out 2>&1 &
	elif [ "${app}" == "kibana" ]; then
		checkFileExist ${KIBANA_BIN_PATH}/kibana
		nohup sh ${KIBANA_BIN_PATH}/kibana >> ${KIBANA_BIN_PATH}/nohup.out 2>&1 &
	elif [ "${app}" == "filebeat" ]; then
		checkFileExist ${FILEBEAT_PATH}/filebeat
		touch ${FILEBEAT_PATH}/nohup.out
		nohup ${FI
Download .txt
gitextract_eglus17c/

├── .editorconfig
├── .gitattributes
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── assets/
│   ├── docker.xmind
│   └── linux.xmind
├── codes/
│   ├── docker/
│   │   └── docker-compose-demo/
│   │       ├── Dockerfile
│   │       ├── app.py
│   │       ├── docker-compose.yml
│   │       └── run.sh
│   ├── expect/
│   │   └── 远程登录.sh
│   ├── linux/
│   │   ├── README.md
│   │   ├── build/
│   │   │   ├── Java应用运行脚本模板/
│   │   │   │   ├── lifecycle.sh
│   │   │   │   ├── start.sh
│   │   │   │   ├── stop.sh
│   │   │   │   └── utils.sh
│   │   │   ├── README.md
│   │   │   ├── helper.sh
│   │   │   ├── java-app-boot.sh
│   │   │   ├── java-app-release.sh
│   │   │   ├── java-app-run.sh
│   │   │   ├── js-app-release.sh
│   │   │   ├── main.sh
│   │   │   ├── spring-boot-run.sh
│   │   │   └── update-code.sh
│   │   ├── conf/
│   │   │   └── etc/
│   │   │       └── sysctl.conf
│   │   ├── download.sh
│   │   ├── dunwu-ops.sh
│   │   ├── dunwu-soft.sh
│   │   ├── dunwu-sys.sh
│   │   ├── libtest/
│   │   │   ├── README.md
│   │   │   ├── env-test.sh
│   │   │   ├── git-check.sh
│   │   │   ├── git-update.sh
│   │   │   └── nodejs-test.sh
│   │   ├── soft/
│   │   │   ├── README.md
│   │   │   ├── arthas-install.sh
│   │   │   ├── config/
│   │   │   │   ├── fastdfs/
│   │   │   │   │   ├── client.conf
│   │   │   │   │   ├── storage.conf
│   │   │   │   │   └── tracker.conf
│   │   │   │   ├── mysql/
│   │   │   │   │   └── my.cnf
│   │   │   │   ├── nginx/
│   │   │   │   │   ├── conf/
│   │   │   │   │   │   └── fdfs.conf
│   │   │   │   │   ├── nginx.conf
│   │   │   │   │   └── nginx.service
│   │   │   │   ├── redis/
│   │   │   │   │   ├── cluster/
│   │   │   │   │   │   ├── 27001/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 27002/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 27003/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 27004/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 27005/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 27006/
│   │   │   │   │   │   │   └── sentinel.conf
│   │   │   │   │   │   ├── 7001/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7002/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7003/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7004/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7005/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7006/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7007/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7008/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7009/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7010/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7011/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── 7012/
│   │   │   │   │   │   │   └── redis.conf
│   │   │   │   │   │   ├── README.md
│   │   │   │   │   │   ├── redis-cluster.sh
│   │   │   │   │   │   ├── redis-cluster2.sh
│   │   │   │   │   │   ├── start-cluster.sh
│   │   │   │   │   │   ├── start-cluster2.sh
│   │   │   │   │   │   └── start-sentinel.sh
│   │   │   │   │   ├── redis.conf
│   │   │   │   │   └── redis.service
│   │   │   │   └── settings-aliyun.xml
│   │   │   ├── docker-install.sh
│   │   │   ├── elk/
│   │   │   │   ├── boot-elk.sh
│   │   │   │   ├── config/
│   │   │   │   │   ├── filebeat.yml
│   │   │   │   │   ├── logback.xml
│   │   │   │   │   └── logstash.conf
│   │   │   │   ├── install-elk.sh
│   │   │   │   ├── install_elasticserch.sh
│   │   │   │   ├── install_filebeat.sh
│   │   │   │   ├── install_kibana.sh
│   │   │   │   └── install_logstash.sh
│   │   │   ├── fastdfs-install.sh
│   │   │   ├── gitlab/
│   │   │   │   ├── gitlab-backup.sh
│   │   │   │   └── gitlab.sh
│   │   │   ├── gitlab-install.sh
│   │   │   ├── install_grafana.sh
│   │   │   ├── jdk8-install.sh
│   │   │   ├── jenkins-install.sh
│   │   │   ├── kafka-install.sh
│   │   │   ├── lib/
│   │   │   │   ├── docker.sh
│   │   │   │   ├── file.sh
│   │   │   │   ├── git.sh
│   │   │   │   ├── java.sh
│   │   │   │   ├── maven.sh
│   │   │   │   ├── mysql.sh
│   │   │   │   ├── net.sh
│   │   │   │   ├── nodejs.sh
│   │   │   │   ├── string.sh
│   │   │   │   └── utils.sh
│   │   │   ├── maven-install.sh
│   │   │   ├── mongodb-install.sh
│   │   │   ├── mysql-backup.sh
│   │   │   ├── mysql-install.sh
│   │   │   ├── mysql-recovery.sh
│   │   │   ├── nacos-install.sh
│   │   │   ├── nexus-install.sh
│   │   │   ├── nginx-install.sh
│   │   │   ├── nodejs-install.sh
│   │   │   ├── redis-install.sh
│   │   │   ├── rocketmq-install.sh
│   │   │   ├── tomcat8-install.sh
│   │   │   ├── zookeeper-install.sh
│   │   │   ├── zsh/
│   │   │   │   └── oh-my-zsh-install.sh
│   │   │   └── zsh-install.sh
│   │   ├── sys/
│   │   │   ├── README.md
│   │   │   ├── change-yum-repo.sh
│   │   │   ├── install-libs.sh
│   │   │   ├── install-tools.sh
│   │   │   ├── set-dns.sh
│   │   │   ├── set-ntp.sh
│   │   │   ├── stop-firewall.sh
│   │   │   ├── sys-settings.sh
│   │   │   ├── syscheck.sh
│   │   │   └── yum/
│   │   │       ├── Centos-5.repo
│   │   │       ├── Centos-6.repo
│   │   │       └── Centos-7.repo
│   │   └── tool/
│   │       ├── Autoinstall_ELK_V1.3.sh
│   │       ├── Cpu_Limit.sh
│   │       ├── Custom_Rm.sh
│   │       ├── Daily_Archive.sh
│   │       ├── Hourly_Archive.sh
│   │       ├── gitcheck
│   │       ├── 删除用户脚本.sh
│   │       └── 查看指定目录磁盘使用情况.sh
│   └── shell/
│       ├── README.md
│       ├── lib/
│       │   └── env.sh
│       ├── mysql/
│       │   ├── SQL批处理执行脚本.sh
│       │   ├── 向数据库中插入数据.sh
│       │   ├── 格式化输出数据.sh
│       │   └── 连接数据库并发送命令.sh
│       ├── 基本脚本/
│       │   ├── echo示例.sh
│       │   ├── exit命令.sh
│       │   ├── printf示例.sh
│       │   ├── 使用expr执行数学运算.sh
│       │   ├── 使用内联重定向计算表达式.sh
│       │   ├── 使用方括号执行数学运算.sh
│       │   ├── 反引号的使用.sh
│       │   ├── 变量使用示例.sh
│       │   ├── 在脚本中使用bc.sh
│       │   ├── 字符串使用示例.sh
│       │   ├── 数组使用示例.sh
│       │   ├── 显示时间和登录者.sh
│       │   ├── 显示系统变量和转义字符.sh
│       │   ├── 注释示例.sh
│       │   └── 通过反引号获得当前日期并生成唯一文件名.sh
│       ├── 控制/
│       │   ├── 定时执行脚本.sh
│       │   ├── 捕捉信号.sh
│       │   ├── 捕捉脚本的退出.sh
│       │   └── 移除捕捉.sh
│       ├── 操作符/
│       │   ├── 关系运算符.sh
│       │   ├── 字符串运算符.sh
│       │   ├── 布尔运算符.sh
│       │   ├── 文件测试运算符.sh
│       │   ├── 算术运算符.sh
│       │   └── 逻辑运算符.sh
│       ├── 文件操作/
│       │   ├── log.txt
│       │   ├── 创建临时文件.sh
│       │   ├── 创建临时目录.sh
│       │   ├── 文件路径操作.sh
│       │   ├── 目录基本操作.sh
│       │   └── 读文件.sh
│       ├── 查找替换文本/
│       │   ├── gawk/
│       │   │   ├── gawk.sh
│       │   │   ├── gawk函数库
│       │   │   ├── gawk脚本
│       │   │   ├── script
│       │   │   ├── test
│       │   │   ├── 使用变量.sh
│       │   │   ├── 使用模式,结构化命令.sh
│       │   │   ├── 自定义函数.sh
│       │   │   ├── 调用函数库和脚本.sh
│       │   │   └── 输出.sh
│       │   ├── grep.sh
│       │   ├── regex/
│       │   │   ├── 目录文件计数.sh
│       │   │   └── 邮件验证.sh
│       │   └── sed/
│       │       ├── sed文件操作.sh
│       │       ├── sed编辑器基础.sh
│       │       ├── test
│       │       ├── 保持空间.sh
│       │       ├── 删除指定的空白行和删除html标签.sh
│       │       ├── 在脚本中使用sed.sh
│       │       ├── 排除命令.sh
│       │       ├── 模式替代.sh
│       │       ├── 测试.sh
│       │       ├── 给文件中的行编号.sh
│       │       ├── 跳转.sh
│       │       ├── 输出末尾指定行数的数据.sh
│       │       └── 重定向sed输出.sh
│       ├── 系统管理/
│       │   ├── 控制远程服务器执行指令.sh
│       │   └── 系统用户管理.sh
│       ├── 脚本函数/
│       │   ├── lib.sh
│       │   ├── 从函数返回数组.sh
│       │   ├── 使用return命令.sh
│       │   ├── 使用全局变量带来的问题.sh
│       │   ├── 使用函数输出.sh
│       │   ├── 使用命令行中传递的参数.sh
│       │   ├── 使用局部变量.sh
│       │   ├── 使用库函数.sh
│       │   ├── 全局变量.sh
│       │   ├── 函数入参.sh
│       │   ├── 函数入参2.sh
│       │   ├── 函数基本示例.sh
│       │   ├── 函数基本示例2.sh
│       │   ├── 函数递归.sh
│       │   ├── 在函数中使用参数.sh
│       │   ├── 想函数传数组数据.sh
│       │   ├── 累加数组中的值.sh
│       │   └── 默认退出状态码.sh
│       ├── 菜单/
│       │   ├── 使用msgbox部件.sh
│       │   ├── 使用select命令.sh
│       │   ├── 使用脚本菜单.sh
│       │   └── 在脚本中使用dialog命令.sh
│       ├── 输入和输出/
│       │   ├── test
│       │   ├── test1
│       │   ├── 临时重定向.sh
│       │   ├── 使用getopts.sh
│       │   ├── 使用getopts处理选项和参数.sh
│       │   ├── 使用getopt命令.sh
│       │   ├── 使用shift命令.sh
│       │   ├── 免密码传输.sh
│       │   ├── 分离参数和选项.sh
│       │   ├── 列出当前脚本打开的文件描述符.sh
│       │   ├── 创建自己的重定向/
│       │   │   ├── 从以重定向的文件描述符中恢复.sh
│       │   │   ├── 关闭文件描述符.sh
│       │   │   ├── 创建读写文件描述符.sh
│       │   │   ├── 创建输入文件描述符.sh
│       │   │   └── 创建输出文件描述符.sh
│       │   ├── 参数计数.sh
│       │   ├── 在脚本中使用重定向输入.sh
│       │   ├── 处理带值的选项.sh
│       │   ├── 处理简单选项.sh
│       │   ├── 快速清除文件或日志.sh
│       │   ├── 抓取所有数据.sh
│       │   ├── 永久重定向.sh
│       │   ├── 测试.txt
│       │   ├── 获取用户输入.sh
│       │   ├── 记录信息.sh
│       │   ├── 读取参数.sh
│       │   ├── 读取多个命令行参数.sh
│       │   ├── 读取程序名.sh
│       │   ├── 读取选择参数.sh
│       │   ├── 超时和输入计数.sh
│       │   └── 隐藏方式读取数据.sh
│       ├── 进阶脚本/
│       │   ├── 创建捕捉脚本.sh
│       │   ├── 开启debug模式.sh
│       │   ├── 查看uptime获取在线用户数.sh
│       │   ├── 生成报告脚本-基于创建捕捉脚本.sh
│       │   ├── 系统快照报告.sh
│       │   ├── 输出颜色.sh
│       │   └── 问题跟踪数据库/
│       │       ├── Update_Problem.sh
│       │       ├── 查找问题.sh
│       │       └── 记录问题.sh
│       └── 逻辑控制/
│           ├── bash-shell无法处理浮点数.sh
│           ├── break示例.sh
│           ├── case示例.sh
│           ├── continue示例.sh
│           ├── for循环示例.sh
│           ├── if-elif-else示例.sh
│           ├── output.txt
│           ├── select菜单示例.sh
│           ├── until示例.sh
│           ├── while循环示例.sh
│           ├── 从命令读取值.sh
│           ├── 使用双圆括号.sh
│           ├── 使用双方括号.sh
│           ├── 使用大于小于号.sh
│           ├── 使用嵌套循环并修改IFS.sh
│           ├── 使用管道或重定向.sh
│           ├── 使用通配符处理目录.sh
│           ├── 注意test大小写顺序和sort不同.sh
│           └── 读取里表中复杂的值.sh
├── docs/
│   ├── .remarkrc
│   ├── .textlint.terms.json
│   ├── .textlintrc.js
│   ├── .vuepress/
│   │   ├── config.js
│   │   └── enhanceApp.js
│   ├── README.md
│   ├── docker/
│   │   ├── README.md
│   │   ├── docker-cheat-sheet.md
│   │   ├── docker-compose.md
│   │   ├── docker-dockerfile.md
│   │   ├── docker-quickstart.md
│   │   ├── docker.xmind
│   │   ├── kubernetes.md
│   │   └── service/
│   │       ├── docker-install-mysql.md
│   │       └── docker-install-nginx.md
│   ├── linux/
│   │   ├── cli/
│   │   │   ├── README.md
│   │   │   ├── free.md
│   │   │   ├── grep.md
│   │   │   ├── iostat.md
│   │   │   ├── iotop.md
│   │   │   ├── linux-cli-dir.md
│   │   │   ├── linux-cli-file-compress.md
│   │   │   ├── linux-cli-file.md
│   │   │   ├── linux-cli-hardware.md
│   │   │   ├── linux-cli-help.md
│   │   │   ├── linux-cli-net.md
│   │   │   ├── linux-cli-software.md
│   │   │   ├── linux-cli-system.md
│   │   │   ├── linux-cli-user.md
│   │   │   ├── scp.md
│   │   │   ├── top.md
│   │   │   ├── vmstat.md
│   │   │   └── 命令行的艺术.md
│   │   ├── expect.md
│   │   ├── ops/
│   │   │   ├── README.md
│   │   │   ├── crontab.md
│   │   │   ├── firewalld.md
│   │   │   ├── iptables.md
│   │   │   ├── network-ops.md
│   │   │   ├── ntp.md
│   │   │   ├── samba.md
│   │   │   ├── systemd.md
│   │   │   ├── vim.md
│   │   │   └── zsh.md
│   │   └── soft/
│   │       ├── README.md
│   │       ├── apollo/
│   │       │   ├── README.md
│   │       │   └── apollo.xmind
│   │       ├── elastic/
│   │       │   ├── README.md
│   │       │   ├── elastic-beats.md
│   │       │   ├── elastic-kibana.md
│   │       │   ├── elastic-logstash.md
│   │       │   └── elastic-quickstart.md
│   │       ├── fastdfs.md
│   │       ├── gitlab-ops.md
│   │       ├── jdk-install.md
│   │       ├── jenkins-ops.md
│   │       ├── kafka-install.md
│   │       ├── maven-install.md
│   │       ├── mongodb-ops.md
│   │       ├── nacos-install.md
│   │       ├── nexus-ops.md
│   │       ├── nodejs-install.md
│   │       ├── rocketmq-install.md
│   │       ├── svn-ops.md
│   │       ├── tomcat-install.md
│   │       └── yapi-ops.md
│   ├── mac/
│   │   └── soft/
│   │       └── ruby-install.md
│   └── package.json
└── scripts/
    └── deploy.sh
Download .txt
SYMBOL INDEX (1 symbols across 1 files)

FILE: codes/docker/docker-compose-demo/app.py
  function hello (line 8) | def hello():
Condensed preview — 351 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (823K chars).
[
  {
    "path": ".editorconfig",
    "chars": 493,
    "preview": "# EditorConfig 用于在 IDE 中检查代码的基本 Code Style\n# @see: https://editorconfig.org/\n\n# 配置说明:\n# 所有文件换行使用 Unix 风格(LF),*.bat 文件使用 "
  },
  {
    "path": ".gitattributes",
    "chars": 870,
    "preview": "* text=auto eol=lf\n\n# plan text\n*.txt text\n*.java text\n*.scala text\n*.groovy text\n*.gradle text\n*.xml text\n*.xsd text\n*."
  },
  {
    "path": ".gitignore",
    "chars": 981,
    "preview": "# ---------------------------------------------------------------------\n# more gitignore templates see https://github.co"
  },
  {
    "path": ".travis.yml",
    "chars": 337,
    "preview": "# 持续集成 CI\n# @see https://docs.travis-ci.com/user/tutorial/\n\nlanguage: node_js\n\nsudo: required\n\nnode_js: '16.13.0'\n\nbranc"
  },
  {
    "path": "LICENSE",
    "chars": 20127,
    "preview": "Attribution-ShareAlike 4.0 International\n\n=======================================================================\n\nCreat"
  },
  {
    "path": "README.md",
    "chars": 7577,
    "preview": "<p align=\"center\">\n    <a href=\"https://dunwu.github.io/linux-tutorial/\" target=\"_blank\" rel=\"noopener noreferrer\">\n    "
  },
  {
    "path": "codes/docker/docker-compose-demo/Dockerfile",
    "chars": 102,
    "preview": "FROM python:3.6-alpine\nADD . /code\nWORKDIR /code\nRUN pip install redis flask\nCMD [\"python\", \"app.py\"]\n"
  },
  {
    "path": "codes/docker/docker-compose-demo/app.py",
    "chars": 295,
    "preview": "from flask import Flask\nfrom redis import Redis\n\napp = Flask(__name__)\nredis = Redis(host='redis', port=6379)\n\n@app.rout"
  },
  {
    "path": "codes/docker/docker-compose-demo/docker-compose.yml",
    "chars": 111,
    "preview": "version: '3'\nservices:\n\n  web:\n    build: .\n    ports:\n      - \"5000:5000\"\n\n  redis:\n    image: \"redis:alpine\"\n"
  },
  {
    "path": "codes/docker/docker-compose-demo/run.sh",
    "chars": 46,
    "preview": "#!/usr/bin/env bash\n\nset -x\ndocker-compose up\n"
  },
  {
    "path": "codes/expect/远程登录.sh",
    "chars": 637,
    "preview": "#!/usr/bin/expect -f\n\n# ------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/README.md",
    "chars": 499,
    "preview": "# CentOS 常规操作运维脚本集合\n\n> **本项目脚本代码用于在 [CentOS](https://www.centos.org/) 机器上安装常用命令工具或开发软件。**\n\n使用说明:\n\n(1)下载脚本\n\n```shell\ncurl"
  },
  {
    "path": "codes/linux/build/Java应用运行脚本模板/lifecycle.sh",
    "chars": 5946,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/build/Java应用运行脚本模板/start.sh",
    "chars": 1128,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/build/Java应用运行脚本模板/stop.sh",
    "chars": 673,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/build/Java应用运行脚本模板/utils.sh",
    "chars": 3210,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/build/README.md",
    "chars": 39,
    "preview": "# 构建、编译项目脚本\n\n> 目前支持 Java、Javascript 应用\n"
  },
  {
    "path": "codes/linux/build/helper.sh",
    "chars": 1364,
    "preview": "#!/usr/bin/env bash\n\n# 打印UI页头信息\nfunction printHeadInfo() {\n\tcat << EOF\n*************************************************"
  },
  {
    "path": "codes/linux/build/java-app-boot.sh",
    "chars": 2233,
    "preview": "#!/usr/bin/env bash\n\n#################################################################################\n# JAVA 应用通用启动脚本\n#"
  },
  {
    "path": "codes/linux/build/java-app-release.sh",
    "chars": 2620,
    "preview": "#!/usr/bin/env bash\n\n#################################################################################\n# JAVA 应用发布脚本\n# @"
  },
  {
    "path": "codes/linux/build/java-app-run.sh",
    "chars": 1846,
    "preview": "#!/usr/bin/env bash\n\n#################################################################################\n# JAVA 应用运行脚本\n# @"
  },
  {
    "path": "codes/linux/build/js-app-release.sh",
    "chars": 1565,
    "preview": "#################################################################################\n# 前端应用发布脚本\n# 环境要求:Nvm、Node.js\n########"
  },
  {
    "path": "codes/linux/build/main.sh",
    "chars": 3186,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 项目发布脚本模板\n# @a"
  },
  {
    "path": "codes/linux/build/spring-boot-run.sh",
    "chars": 4043,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n# console color\nBLAC"
  },
  {
    "path": "codes/linux/build/update-code.sh",
    "chars": 2679,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 更新代码脚本\n# 只有退出"
  },
  {
    "path": "codes/linux/conf/etc/sysctl.conf",
    "chars": 2012,
    "preview": "###################################################################################\n# /etc/sysctl.conf 文件用于配置 Linux 内核及网"
  },
  {
    "path": "codes/linux/download.sh",
    "chars": 1354,
    "preview": "#!/usr/bin/env bash\n\n# ---------------------------------------------------------------------------------\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/dunwu-ops.sh",
    "chars": 5059,
    "preview": "#!/usr/bin/env bash\n\n# ------------------------------------------------------------------------------\n# CentOS 常用软件一键安装脚"
  },
  {
    "path": "codes/linux/dunwu-soft.sh",
    "chars": 4930,
    "preview": "#!/usr/bin/env bash\n\n# ------------------------------------------------------------------------------\n# CentOS 常用软件一键安装脚"
  },
  {
    "path": "codes/linux/dunwu-sys.sh",
    "chars": 4950,
    "preview": "#!/usr/bin/env bash\n\n# ------------------------------------------------------------------------------\n# CentOS 环境初始化脚本\n#"
  },
  {
    "path": "codes/linux/libtest/README.md",
    "chars": 286,
    "preview": "# Git 脚本工具\n\n这里汇总一些常用的、简单的 git shell 脚本。\n\n更多功能强大的工具,可以参考 [资源](#资源)\n\n## 资源\n\n- [git-extras](https://github.com/tj/git-extra"
  },
  {
    "path": "codes/linux/libtest/env-test.sh",
    "chars": 1297,
    "preview": "#!/usr/bin/env bash\n\n# 装载其它库\nsource ../lib/utils.sh\n\n# -----------------------------------------------------------------"
  },
  {
    "path": "codes/linux/libtest/git-check.sh",
    "chars": 544,
    "preview": "#!/usr/bin/env bash\n\nsource ../lib/utils.sh\nsource ../lib/git.sh\n\n##################################### MAIN ###########"
  },
  {
    "path": "codes/linux/libtest/git-update.sh",
    "chars": 1025,
    "preview": "#!/usr/bin/env bash\n\nsource ../lib/utils.sh\nsource ../lib/git.sh\n\ndoCloneOrPullGit() {\n    cloneOrPullGit $1 $2 $3 $4 $5"
  },
  {
    "path": "codes/linux/libtest/nodejs-test.sh",
    "chars": 286,
    "preview": "#!/usr/bin/env bash\n\n# 装载其它库\nsource ../lib/nodejs.sh\n\n# ----------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/README.md",
    "chars": 5386,
    "preview": "# 服务安装配置\n\n<!-- TOC depthFrom:2 depthTo:3 -->\n\n- [oh-my-zsh 安装](#oh-my-zsh-安装)\n- [JDK8 安装](#jdk8-安装)\n- [Maven 安装配置](#mave"
  },
  {
    "path": "codes/linux/soft/arthas-install.sh",
    "chars": 876,
    "preview": "#!/usr/bin/env bash\n\n# ----------------------------------------------------------------------------------\n# 控制台颜色\nBLACK="
  },
  {
    "path": "codes/linux/soft/config/fastdfs/client.conf",
    "chars": 1447,
    "preview": "# connect timeout in seconds\n# default value is 30s\nconnect_timeout=30\n\n# network timeout in seconds\n# default value is "
  },
  {
    "path": "codes/linux/soft/config/fastdfs/storage.conf",
    "chars": 7936,
    "preview": "# is this config file disabled\n# false for enabled\n# true for disabled\ndisabled=false\n\n# the name of the group this stor"
  },
  {
    "path": "codes/linux/soft/config/fastdfs/tracker.conf",
    "chars": 7423,
    "preview": "# is this config file disabled\n# false for enabled\n# true for disabled\ndisabled=false\n\n# bind an address of this host\n# "
  },
  {
    "path": "codes/linux/soft/config/mysql/my.cnf",
    "chars": 1389,
    "preview": "# -------------------------------------------------------------------------------\n# Mysql 基本配置模板\n# ---------------------"
  },
  {
    "path": "codes/linux/soft/config/nginx/conf/fdfs.conf",
    "chars": 245,
    "preview": "server {\n  listen       7001;    ## 该端口为storage.conf中的http.server_port相同\n  server_name  localhost;\n  location ~/group[0-"
  },
  {
    "path": "codes/linux/soft/config/nginx/nginx.conf",
    "chars": 904,
    "preview": "worker_processes 1;\n\nerror_log logs/error.log;\n#error_log logs/error.log notice;\n#error_log logs/error.log info;\npid /us"
  },
  {
    "path": "codes/linux/soft/config/nginx/nginx.service",
    "chars": 486,
    "preview": "[Unit]\nDescription=The NGINX HTTP and reverse proxy server\nAfter=syslog.target network.target remote-fs.target nss-looku"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/27001/sentinel.conf",
    "chars": 294,
    "preview": "port 27001\ndaemonize yes\nsentinel monitor redis-master 172.22.6.3 7001 2\nsentinel down-after-milliseconds redis-master 5"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/27002/sentinel.conf",
    "chars": 294,
    "preview": "port 27002\ndaemonize yes\nsentinel monitor redis-master 172.22.6.3 7002 2\nsentinel down-after-milliseconds redis-master 5"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/27003/sentinel.conf",
    "chars": 294,
    "preview": "port 27003\ndaemonize yes\nsentinel monitor redis-master 172.22.6.3 7003 2\nsentinel down-after-milliseconds redis-master 5"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/27004/sentinel.conf",
    "chars": 295,
    "preview": "port 27004\ndaemonize yes\nsentinel monitor redis-master 172.22.6.3 7007 2\nsentinel down-after-milliseconds redis-master 5"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/27005/sentinel.conf",
    "chars": 295,
    "preview": "port 27005\ndaemonize yes\nsentinel monitor redis-master 172.22.6.3 7008 2\nsentinel down-after-milliseconds redis-master 5"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/27006/sentinel.conf",
    "chars": 295,
    "preview": "port 27006\ndaemonize yes\nsentinel monitor redis-master 172.22.6.3 7009 2\nsentinel down-after-milliseconds redis-master 5"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7001/redis.conf",
    "chars": 280,
    "preview": "port 7001\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7001/7001.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7002/redis.conf",
    "chars": 280,
    "preview": "port 7002\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7002/7002.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7003/redis.conf",
    "chars": 280,
    "preview": "port 7003\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7003/7003.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7004/redis.conf",
    "chars": 280,
    "preview": "port 7004\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7004/7004.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7005/redis.conf",
    "chars": 280,
    "preview": "port 7005\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7005/7005.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7006/redis.conf",
    "chars": 280,
    "preview": "port 7006\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7006/7006.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7007/redis.conf",
    "chars": 280,
    "preview": "port 7007\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7007/7007.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7008/redis.conf",
    "chars": 280,
    "preview": "port 7008\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7008/7008.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7009/redis.conf",
    "chars": 280,
    "preview": "port 7009\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7009/7009.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7010/redis.conf",
    "chars": 280,
    "preview": "port 7010\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7010/7010.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7011/redis.conf",
    "chars": 280,
    "preview": "port 7011\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7011/7011.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/7012/redis.conf",
    "chars": 280,
    "preview": "port 7012\nbind 172.22.6.3\ndaemonize yes\n\ncluster-enabled yes\ncluster-config-file /usr/local/redis/conf/7012/7012.conf\ncl"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/README.md",
    "chars": 1059,
    "preview": "# Redis 集群配置\n\n## 使用方式\n\n集群拓扑:\n\n- 三主三从\n- 三哨兵\n\n启动方式:\n\n- 先执行 redis-cluster.sh,会自动根据 7001 ~ 7006 目录启动服务器,并将其配置为集群。\n- 再执行 star"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/redis-cluster.sh",
    "chars": 2229,
    "preview": "#!/usr/bin/env bash\n\n# Settings\nHOST=\"172.22.6.3\"\nPORT=7000\nTIMEOUT=2000\nNODES=6\nREPLICAS=1\nENDPORT=$((PORT+NODES))\n\n# Y"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/redis-cluster2.sh",
    "chars": 2230,
    "preview": "#!/usr/bin/env bash\n\n# Settings\nHOST=\"172.22.6.3\"\nPORT=7000\nTIMEOUT=2000\nNODES=12\nREPLICAS=1\nENDPORT=$((PORT+NODES))\n\n# "
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/start-cluster.sh",
    "chars": 707,
    "preview": "#!/usr/bin/env bash\n\nPORT=6380\nNODES=6\nENDPORT=$((PORT+NODES))\n\n# 启动 4 个 redis server\nwhile [[ $((PORT < ENDPORT)) != \"0"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/start-cluster2.sh",
    "chars": 892,
    "preview": "#!/usr/bin/env bash\n\n# 启动 4 个 redis server\n/opt/redis/src/redis-server /usr/local/redis/conf/6381/redis.conf\n/opt/redis/"
  },
  {
    "path": "codes/linux/soft/config/redis/cluster/start-sentinel.sh",
    "chars": 432,
    "preview": "/opt/redis/src/redis-sentinel /usr/local/redis/conf/27001/sentinel.conf\n/opt/redis/src/redis-sentinel /usr/local/redis/c"
  },
  {
    "path": "codes/linux/soft/config/redis/redis.conf",
    "chars": 62156,
    "preview": "# Redis configuration file example.\n#\n# Note that in order to read the configuration file, Redis must be\n# started with "
  },
  {
    "path": "codes/linux/soft/config/redis/redis.service",
    "chars": 301,
    "preview": "[Unit]\nDescription=Redis\nAfter=network.target\n\n[Service]\nType=forking\nPIDFile=/var/run/redis/redis-6379.pid\nExecStart=/u"
  },
  {
    "path": "codes/linux/soft/config/settings-aliyun.xml",
    "chars": 651,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<settings xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txmlns=\"http://m"
  },
  {
    "path": "codes/linux/soft/docker-install.sh",
    "chars": 1796,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/elk/boot-elk.sh",
    "chars": 2029,
    "preview": "#!/usr/bin/env bash\n\n# 检查脚本输入参数\ncheckInput() {\n\tif [ \"${app}\" == \"\" ] || [ \"${oper}\" == \"\" ]; then\n\t\techo \"请输入脚本参数:name\""
  },
  {
    "path": "codes/linux/soft/elk/config/filebeat.yml",
    "chars": 6553,
    "preview": "###################### Filebeat Configuration Example #########################\n\n# This file is an example configuration"
  },
  {
    "path": "codes/linux/soft/elk/config/logback.xml",
    "chars": 1762,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n<!-- logback中一共有5种有效级别,分别是TRACE、DEBUG、INFO、WARN、ERROR,优先级依次从低到高 -->\n<configurat"
  },
  {
    "path": "codes/linux/soft/elk/config/logstash.conf",
    "chars": 191,
    "preview": "input {\n tcp {\n   port => 9251\n   codec => json_lines\n   mode => server\n   tags => [\"javaapp\"]\n }\n}\noutput {\n  elasticse"
  },
  {
    "path": "codes/linux/soft/elk/install-elk.sh",
    "chars": 4148,
    "preview": "#!/usr/bin/env bash\n\n# 本脚本为一键式安装 ELK 脚本\n# 执行脚本前,请先执行以下命令,创建用户\n# groupadd elk\n# useradd -g elk elk\n# passwd elk\n\n# 获取当前设备"
  },
  {
    "path": "codes/linux/soft/elk/install_elasticserch.sh",
    "chars": 5874,
    "preview": "#!/usr/bin/env bash\n\n# auth:kaliarch\n# version:v1.0\n# func:elasticsearch 5.4.1/6.0.1/6.3.1安装\n# 定义安装目录、及日志信息\n. /etc/init."
  },
  {
    "path": "codes/linux/soft/elk/install_filebeat.sh",
    "chars": 4055,
    "preview": "#!/usr/bin/env bash\n\n# auth:kaliarch\n# version:v1.0\n# func:filebeat 5.6.1/6.1.3/6.3.2 安装\n\n# 定义安装目录、及日志信息\n. /etc/init.d/f"
  },
  {
    "path": "codes/linux/soft/elk/install_kibana.sh",
    "chars": 4041,
    "preview": "#!/usr/bin/env bash\n\n# auth:kaliarch\n# version:v1.0\n# func:kibana 6.0.1/6.2.4/6.3.1 安装\n\n# 定义安装目录、及日志信息\n. /etc/init.d/fun"
  },
  {
    "path": "codes/linux/soft/elk/install_logstash.sh",
    "chars": 4101,
    "preview": "#!/usr/bin/env bash\n\n# auth:kaliarch\n# version:v1.0\n# func:logstash 5.4/6.1/6.3 安装\n\n# 定义安装目录、及日志信息\n. /etc/init.d/functio"
  },
  {
    "path": "codes/linux/soft/fastdfs-install.sh",
    "chars": 6699,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/gitlab/gitlab-backup.sh",
    "chars": 1376,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/gitlab/gitlab.sh",
    "chars": 5451,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/gitlab-install.sh",
    "chars": 3117,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/install_grafana.sh",
    "chars": 3259,
    "preview": "#!/usr/bin/env bash\n\n# auth:kaliarch\n# version:v1.0\n# func:grafana 5.1.0/5.1.5/5.2.2 安装\n\n# 定义安装目录、及日志信息\n. /etc/init.d/fu"
  },
  {
    "path": "codes/linux/soft/jdk8-install.sh",
    "chars": 947,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/jenkins-install.sh",
    "chars": 414,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 安装 Jenkins 脚本"
  },
  {
    "path": "codes/linux/soft/kafka-install.sh",
    "chars": 1527,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/lib/docker.sh",
    "chars": 2187,
    "preview": "#!/usr/bin/env bash\n\nLINUX_SCRIPTS_LIB_DIR=`dirname ${BASH_SOURCE[0]}`\nsource ${LINUX_SCRIPTS_LIB_DIR}/utils.sh\n\ndockerB"
  },
  {
    "path": "codes/linux/soft/lib/file.sh",
    "chars": 1262,
    "preview": "#!/usr/bin/env bash\n\n# 装载其它库\nROOT=`dirname ${BASH_SOURCE[0]}`\nsource ${ROOT}/utils.sh\n\n# -------------------------------"
  },
  {
    "path": "codes/linux/soft/lib/git.sh",
    "chars": 6032,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/lib/java.sh",
    "chars": 4769,
    "preview": "#!/usr/bin/env bash\n\n# ------------------------------------------------------------------------------\n# Java 应用运维脚本\n# @a"
  },
  {
    "path": "codes/linux/soft/lib/maven.sh",
    "chars": 1876,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/lib/mysql.sh",
    "chars": 7060,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/lib/net.sh",
    "chars": 838,
    "preview": "#!/usr/bin/env bash\n\n# ----------------------------------------------------------------------------------\n# 控制台颜色\nBLACK="
  },
  {
    "path": "codes/linux/soft/lib/nodejs.sh",
    "chars": 2797,
    "preview": "#!/usr/bin/env bash\n\n# 装载其它库\nROOT=`dirname ${BASH_SOURCE[0]}`\nsource ${ROOT}/file.sh\n\n# --------------------------------"
  },
  {
    "path": "codes/linux/soft/lib/string.sh",
    "chars": 638,
    "preview": "#!/usr/bin/env bash\n\nstrIsEmpty() {\n    if [[ -z $1 ]]; then\n       return ${YES}\n    else\n       return ${NO}\n    fi\n}\n"
  },
  {
    "path": "codes/linux/soft/lib/utils.sh",
    "chars": 3623,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/maven-install.sh",
    "chars": 2157,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/mongodb-install.sh",
    "chars": 1448,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/mysql-backup.sh",
    "chars": 1362,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/mysql-install.sh",
    "chars": 3737,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/mysql-recovery.sh",
    "chars": 1203,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/nacos-install.sh",
    "chars": 1258,
    "preview": "#!/usr/bin/env bash\n\ncat << EOF\n\n###################################################################################\n# 安"
  },
  {
    "path": "codes/linux/soft/nexus-install.sh",
    "chars": 3904,
    "preview": "#!/usr/bin/env bash\n\n# -------------------------------------------------------------------------------------------------"
  },
  {
    "path": "codes/linux/soft/nginx-install.sh",
    "chars": 2430,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/nodejs-install.sh",
    "chars": 1467,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/redis-install.sh",
    "chars": 3153,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/rocketmq-install.sh",
    "chars": 1683,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/tomcat8-install.sh",
    "chars": 1447,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/zookeeper-install.sh",
    "chars": 1454,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/soft/zsh/oh-my-zsh-install.sh",
    "chars": 8812,
    "preview": "# -------------------------------------------------------------------------------------------------------------------\n# "
  },
  {
    "path": "codes/linux/soft/zsh-install.sh",
    "chars": 1927,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/sys/README.md",
    "chars": 2204,
    "preview": "# 脚本使用说明\n\n> 建议按照顺序执行本文脚本。\n\n<!-- TOC depthFrom:2 depthTo:3 -->\n\n- [替换 yum repo 源](#替换-yum-repo-源)\n- [安装基本工具(可选)](#安装基本工具可"
  },
  {
    "path": "codes/linux/sys/change-yum-repo.sh",
    "chars": 2004,
    "preview": "#!/usr/bin/env bash\n\n# ---------------------------------------------------------------------------------\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/sys/install-libs.sh",
    "chars": 1242,
    "preview": "#!/usr/bin/env bash\n\n# ---------------------------------------------------------------------------------\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/sys/install-tools.sh",
    "chars": 2706,
    "preview": "#!/usr/bin/env bash\n\n# ---------------------------------------------------------------------------------\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/sys/set-dns.sh",
    "chars": 1026,
    "preview": "#!/usr/bin/env bash\n\n# ---------------------------------------------------------------------------------\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/sys/set-ntp.sh",
    "chars": 1288,
    "preview": "#!/usr/bin/env bash\n\n# ---------------------------------------------------------------------------------\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/sys/stop-firewall.sh",
    "chars": 700,
    "preview": "#!/usr/bin/env bash\n\n# ---------------------------------------------------------------------------------\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/sys/sys-settings.sh",
    "chars": 3206,
    "preview": "#!/usr/bin/env bash\n\n# ---------------------------------------------------------------------------------\n# 控制台颜色\nBLACK=\""
  },
  {
    "path": "codes/linux/sys/syscheck.sh",
    "chars": 7207,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n# console color\nC_RE"
  },
  {
    "path": "codes/linux/sys/yum/Centos-5.repo",
    "chars": 1075,
    "preview": "[base]\nname=CentOS-$releasever - Base\nbaseurl=http://vault.centos.org/$releasever/os/$basearch/\ngpgcheck=1\ngpgkey=file:/"
  },
  {
    "path": "codes/linux/sys/yum/Centos-6.repo",
    "chars": 2523,
    "preview": "# CentOS-Base.repo\n#\n# The mirror system uses the connecting IP address of the client and the\n# update status of each mi"
  },
  {
    "path": "codes/linux/sys/yum/Centos-7.repo",
    "chars": 2523,
    "preview": "# CentOS-Base.repo\n#\n# The mirror system uses the connecting IP address of the client and the\n# update status of each mi"
  },
  {
    "path": "codes/linux/tool/Autoinstall_ELK_V1.3.sh",
    "chars": 4997,
    "preview": "#!/usr/bin/env bash\n\n#mail:xuel@anchnet.com\n#data:2017/9/7\n#AutoInstall ELK scripts\n#Software:elasticsearch-5.4.1/logsta"
  },
  {
    "path": "codes/linux/tool/Cpu_Limit.sh",
    "chars": 1045,
    "preview": "#!/usr/bin/env bash\n\n# auth:kaliarch\n# func:sys info check\n# version:v1.0\n# sys:centos6.x/7.x\n\nset -e\n[ $(id -u) -gt 0 ]"
  },
  {
    "path": "codes/linux/tool/Custom_Rm.sh",
    "chars": 642,
    "preview": "#!/usr/bin/env bash\n\n# function:自定义rm命令,每天晚上定时清理\n\nCMD_SCRIPTS=$HOME/.rm_scripts.sh\nTRASH_DIR=$HOME/.TRASH_DIR\nCRON_FILE="
  },
  {
    "path": "codes/linux/tool/Daily_Archive.sh",
    "chars": 1564,
    "preview": "#!/usr/bin/env bash\n\n#\n# Daily_Archive - Archive designated files & directories\n########################################"
  },
  {
    "path": "codes/linux/tool/Hourly_Archive.sh",
    "chars": 1753,
    "preview": "#!/usr/bin/env bash\n\n#\n# Hourly_Archive - Every hour create an archive\n#################################################"
  },
  {
    "path": "codes/linux/tool/gitcheck",
    "chars": 7542,
    "preview": "#!/bin/sh\n\n###################################################################################\n# 此脚本用于检测 git 状态\n# Copy f"
  },
  {
    "path": "codes/linux/tool/删除用户脚本.sh",
    "chars": 5792,
    "preview": "#!/usr/bin/env bash\n\n#\n# Delete_User - Automates the 4 steps to remove an account\n#\n####################################"
  },
  {
    "path": "codes/linux/tool/查看指定目录磁盘使用情况.sh",
    "chars": 361,
    "preview": "#!/usr/bin/env bash\n\n#DIRS=\"/var/log /home /opt\"\n\n#DATE=$(date '+%m%d%y')\n#exec > disk_space_${DATE}.log\n\necho \"Top Ten "
  },
  {
    "path": "codes/shell/README.md",
    "chars": 269,
    "preview": "# Shell 脚本大全\n\n> **Shell 脚本大全** 精心收集、整理了 Linux 环境下的常见 Shell 脚本操作片段。\n>\n> 当您面临以下问题时,**Shell 脚本大全** 也许可以给你一些借鉴:\n>\n> - 你想要执行某"
  },
  {
    "path": "codes/shell/lib/env.sh",
    "chars": 1042,
    "preview": "#!/usr/bin/env bash\n\n# ------------------------------------------------------------------------------ 颜色状态\n\n# Regular Co"
  },
  {
    "path": "codes/shell/mysql/SQL批处理执行脚本.sh",
    "chars": 183,
    "preview": "#!/usr/bin/env bash\n\nuser='root'\npassword='xxxxxx'\ndatabase='test'\n\nfor f in `ls */*.sql`\ndo\n\techo ${f};\n\tmysql -u${user"
  },
  {
    "path": "codes/shell/mysql/向数据库中插入数据.sh",
    "chars": 396,
    "preview": "#!/usr/bin/env bash\n\n# send data to the the table in the MYSQL database\n\nMYSQL=`which mysql`\n\nif [ $# -ne 2 ]\nthen\n\techo"
  },
  {
    "path": "codes/shell/mysql/格式化输出数据.sh",
    "chars": 294,
    "preview": "#!/usr/bin/env bash\n\n#redirecting SQL output to a variable\n\nMYSQL=`which mysql`\ndbs=`$MYSQL emwjs -u test -Bse 'show tab"
  },
  {
    "path": "codes/shell/mysql/连接数据库并发送命令.sh",
    "chars": 176,
    "preview": "#!/usr/bin/env bash\n\n#连接数据库\nmysql=`which mysql`\n#发送单个命令\n$mysql emwjs -u test -e \"show databases;\"\n\n#发送多个命令\n$mysql emwjs "
  },
  {
    "path": "codes/shell/基本脚本/echo示例.sh",
    "chars": 502,
    "preview": "#!/usr/bin/env bash\n\n# 输出普通字符串\necho \"hello, world\"\n#  Output: hello, world\n\n# 输出含变量的字符串\necho \"hello, \\\"zp\\\"\"\n#  Output: "
  },
  {
    "path": "codes/shell/基本脚本/exit命令.sh",
    "chars": 141,
    "preview": "#!/usr/bin/env bash\n\n#退出状态码,最大为255,超过则进行模运算\n#testing the exit status\nvar1=10\nvar2=20\nvar3=$[ $var1 + $var2 ]\necho The an"
  },
  {
    "path": "codes/shell/基本脚本/printf示例.sh",
    "chars": 679,
    "preview": "#!/usr/bin/env bash\n\n# 单引号\nprintf '%d %s\\n' 1 \"abc\"\n#  Output:1 abc\n\n# 双引号\nprintf \"%d %s\\n\" 1 \"abc\"\n#  Output:1 abc\n\n# 无"
  },
  {
    "path": "codes/shell/基本脚本/使用expr执行数学运算.sh",
    "chars": 130,
    "preview": "#!/usr/bin/env bash\n\n#An example of using the expr command\n\nvar1=10\nvar2=20\nvar3=`expr $var2 / $var1`\necho \"The result i"
  },
  {
    "path": "codes/shell/基本脚本/使用内联重定向计算表达式.sh",
    "chars": 183,
    "preview": "#!/usr/bin/env bash\n\nvar1=10.45\nvar2=43.67\nvar3=33.2\nvar4=71\n\nvar5=`bc << EOF\nscale=4\na1 = $var1 * $var2\nb1 = $var3 * $v"
  },
  {
    "path": "codes/shell/基本脚本/使用方括号执行数学运算.sh",
    "chars": 114,
    "preview": "#!/usr/bin/env bash\n\nvar1=10\nvar2=50\nvar3=45\nvar4=$[ $var1 * ( $var2 - $var3 ) ]\necho 'The final result is '$var4\n"
  },
  {
    "path": "codes/shell/基本脚本/反引号的使用.sh",
    "chars": 123,
    "preview": "#!/usr/bin/env bash\n\n#using the backtick character  会把反引号里面当作一条命令来执行\n\ntesting=`date`\necho \"The date and time are:$testin"
  },
  {
    "path": "codes/shell/基本脚本/变量使用示例.sh",
    "chars": 1072,
    "preview": "#!/usr/bin/env bash\n\n################### 声明变量 ###################\nname=\"world\"\necho \"hello ${name}\"\n# Output: hello worl"
  },
  {
    "path": "codes/shell/基本脚本/在脚本中使用bc.sh",
    "chars": 115,
    "preview": "#!/usr/bin/env bash\n\nvar1=100\nvar2=45\nvar3=`echo \"scale=4; $var1 / $var2\" | bc`\necho The answer for this is $var3\n\n"
  },
  {
    "path": "codes/shell/基本脚本/字符串使用示例.sh",
    "chars": 2056,
    "preview": "#!/usr/bin/env bash\n\n################### 使用单引号拼接字符串 ###################\nname1='white'\nstr1='hello, '${name1}''\nstr2='hel"
  },
  {
    "path": "codes/shell/基本脚本/数组使用示例.sh",
    "chars": 1014,
    "preview": "#!/usr/bin/env bash\n\n################### 创建数组 ###################\nnums=( [ 2 ] = 2 [ 0 ] = 0 [ 1 ] = 1 )\ncolors=( red ye"
  },
  {
    "path": "codes/shell/基本脚本/显示时间和登录者.sh",
    "chars": 182,
    "preview": "#!/usr/bin/env bash\n\n#This script displays the date and who's logged on\n\n#如果想在同一行显示\n#echo -n -e 'The time is:\\n\\n'\necho "
  },
  {
    "path": "codes/shell/基本脚本/显示系统变量和转义字符.sh",
    "chars": 178,
    "preview": "#!/usr/bin/env bash\n\n#display user information from system\n\necho \"User info fro userId:$USER\"\necho UID:$UID\necho HOME:$H"
  },
  {
    "path": "codes/shell/基本脚本/注释示例.sh",
    "chars": 285,
    "preview": "#!/usr/bin/env bash\n\n#--------------------------------------------\n# shell 注释示例\n# author:zp\n#---------------------------"
  },
  {
    "path": "codes/shell/基本脚本/通过反引号获得当前日期并生成唯一文件名.sh",
    "chars": 123,
    "preview": "#!/usr/bin/env bash\n\n#copy the /usr/bin directory listing to a log file\n\ntoday=`date +%y%m%d`\nls /usr/bin -al > log.$tod"
  },
  {
    "path": "codes/shell/控制/定时执行脚本.sh",
    "chars": 64,
    "preview": "#!/usr/bin/env bash\n\n# testing the at command\n\nat -f 4.sh 22:10\n"
  },
  {
    "path": "codes/shell/控制/捕捉信号.sh",
    "chars": 229,
    "preview": "#!/usr/bin/env bash\n\n# testing signal trapping\n\ntrap \"echo'Sorry! I have trapped Ctrl-C'\" SIGINT SIGTERM\n\necho this is a"
  },
  {
    "path": "codes/shell/控制/捕捉脚本的退出.sh",
    "chars": 165,
    "preview": "#!/usr/bin/env bash\n\n# trapping the script exit\n\ntrap \"echobyebye\" EXIT\n\ncount=1\nwhile [ $count -le 5 ]\ndo\n\techo \"Loop #"
  },
  {
    "path": "codes/shell/控制/移除捕捉.sh",
    "chars": 210,
    "preview": "#!/usr/bin/env bash\n\n# removeing a set trap\n\ntrap \"echobyebye\" EXIT\n\ncount=1\nwhile [ $count -le 5 ]\ndo\n\techo \"Loop #$cou"
  },
  {
    "path": "codes/shell/操作符/关系运算符.sh",
    "chars": 872,
    "preview": "#!/usr/bin/env bash\n\nx=10\nif [[ -n $1 ]]; then\n\tx=$1\nfi\n\ny=20\nif [[ -n $2 ]]; then\n\ty=$2\nfi\n\necho \"x=${x}, y=${y}\"\n\nif ["
  },
  {
    "path": "codes/shell/操作符/字符串运算符.sh",
    "chars": 695,
    "preview": "\n#!/usr/bin/env bash\n\nx=\"abc\"\nif [[ -n $1 ]]; then\n\tx=$1\nfi\n\ny=\"xyz\"\nif [[ -n $2 ]]; then\n\ty=$2\nfi\n\necho \"x=${x}, y=${y}"
  },
  {
    "path": "codes/shell/操作符/布尔运算符.sh",
    "chars": 780,
    "preview": "#!/usr/bin/env bash\n\nx=10\nif [[ -n $1 ]]; then\n\tx=$1\nfi\n\ny=20\nif [[ -n $2 ]]; then\n\ty=$2\nfi\n\necho \"x=${x}, y=${y}\"\n\nif ["
  },
  {
    "path": "codes/shell/操作符/文件测试运算符.sh",
    "chars": 764,
    "preview": "#!/usr/bin/env bash\n\nfile=\"/etc/hosts\"\n\nif [[ -r ${file} ]]; then\n\techo \"${file} 文件可读\"\nelse\n\techo \"${file} 文件不可读\"\nfi\nif "
  },
  {
    "path": "codes/shell/操作符/算术运算符.sh",
    "chars": 759,
    "preview": "#!/usr/bin/env bash\n\nx=10\nif [[ -n $1 ]]; then\n\tx=$1\nfi\n\ny=20\nif [[ -n $2 ]]; then\n\ty=$2\nfi\n\necho \"x=${x}, y=${y}\"\n\nval="
  },
  {
    "path": "codes/shell/操作符/逻辑运算符.sh",
    "chars": 500,
    "preview": "#!/usr/bin/env bash\n\nx=10\nif [[ -n $1 ]]; then\n\tx=$1\nfi\n\ny=20\nif [[ -n $2 ]]; then\n\ty=$2\nfi\n\necho \"x=${x}, y=${y}\"\n\nif ["
  },
  {
    "path": "codes/shell/文件操作/log.txt",
    "chars": 2086,
    "preview": "Add git message title here\n\n# See links to relevant web pages, issue trackers, etc.\nSee: https://github.com/\nSee: [Git P"
  },
  {
    "path": "codes/shell/文件操作/创建临时文件.sh",
    "chars": 337,
    "preview": "#!/usr/bin/env bash\n\ntempFile=`mktemp test.XXXXXX`\n\nexec 3> ${tempFile}\n\necho \"This script writes to temp file ${tempFil"
  },
  {
    "path": "codes/shell/文件操作/创建临时目录.sh",
    "chars": 333,
    "preview": "#!/usr/bin/env bash\n\ntempDir=`mktemp -d dir.XXXXXX`\ncd ${tempDir} || exit 1\n\ntempFile1=`mktemp temp.XXXXXX`\ntempFile2=`m"
  },
  {
    "path": "codes/shell/文件操作/文件路径操作.sh",
    "chars": 202,
    "preview": "#!/usr/bin/env bash\n\npath=/dir1/dir2/dir3/test.txt\necho ${path##*/}  获取文件名  test.txt\necho ${path##*.}  获取后缀  txt\n\n#不带后缀的"
  },
  {
    "path": "codes/shell/文件操作/目录基本操作.sh",
    "chars": 772,
    "preview": "#!/usr/bin/env bash\n\n# ------------------------------------------------------------------------------\n# 目录操作示例\n# @author"
  },
  {
    "path": "codes/shell/文件操作/读文件.sh",
    "chars": 152,
    "preview": "#!/usr/bin/env bash\n\nFILE=log.txt\n\ncount=1\ncat ${FILE} | while read line\ndo\n\techo \"$count: $line\"\n\tcount=$[ $count + 1 ]"
  },
  {
    "path": "codes/shell/查找替换文本/gawk/gawk.sh",
    "chars": 245,
    "preview": "#!/usr/bin/env bash\n\nBEGIN {\nprint \"The latest list of users and shells\"\nprint \"Userid\tShell\"\nprint \"------\t-----\"\nFS=\":"
  },
  {
    "path": "codes/shell/查找替换文本/gawk/gawk函数库",
    "chars": 129,
    "preview": "#!/bin/bash\n\nfunction myprint()\n{\n\tprintf \"%-16s - %s\", $1, $4\n}\n\nfunction myrand ( limit )\n{\nreturn int ( limit * rand "
  },
  {
    "path": "codes/shell/查找替换文本/gawk/gawk脚本",
    "chars": 51,
    "preview": "#!/bin/bash\n\nBEGIN{ FS=\"\\n\";\nRS=\"\"}\n{\nmyprint()\n\n}\n"
  },
  {
    "path": "codes/shell/查找替换文本/gawk/script",
    "chars": 34,
    "preview": "BEGIN{FS=\",\"; print n}\n{print $n}\n"
  },
  {
    "path": "codes/shell/查找替换文本/gawk/test",
    "chars": 12,
    "preview": "10\n5\n123\n50\n"
  },
  {
    "path": "codes/shell/查找替换文本/gawk/使用变量.sh",
    "chars": 717,
    "preview": "#!/usr/bin/env bash\n\n#使用内建变量\n\n# NF 当前记录的字段个数\n# NR 到目前为止读的记录数量\n#下面的程序在每行开头输出行号,并在最后输出文件的总字段数\ngawk '{ total+=NF; print NR,"
  },
  {
    "path": "codes/shell/查找替换文本/gawk/使用模式,结构化命令.sh",
    "chars": 468,
    "preview": "#!/usr/bin/env bash\n\n#正则表达式\n\ngawk 'BEGIN{FS=\",\"}\n/11/{print $1}\n' test\n\n#if-else语句\ngawk '{\nif($1 > 20)\n{\n\tx=$1*20\n\tprint"
  },
  {
    "path": "codes/shell/查找替换文本/gawk/自定义函数.sh",
    "chars": 138,
    "preview": "#!/usr/bin/env bash\n\n#gawk 自定义函数\n\ngawk '\nfunction myprint()\n{\n\tprintf \"%-16s - %s\\n\", $1, $4\n}\nBEGIN{FS=\"\\n\"; RS=\"\"}\n{\n\t"
  },
  {
    "path": "codes/shell/查找替换文本/gawk/调用函数库和脚本.sh",
    "chars": 67,
    "preview": "#!/usr/bin/env bash\n\n#使用函数库和gawk脚本\n\ngawk -f gawk函数库 -f gawk脚本 test\n"
  },
  {
    "path": "codes/shell/查找替换文本/gawk/输出.sh",
    "chars": 1211,
    "preview": "#!/usr/bin/env bash\n\n#print用于产生简单输出\n#多个表达式的字符串值之间用输出字段分隔符分开\n\ngawk '{ print $1, $2 }'\n\n#输出字段分割符与输出记录分隔符存储在内建变量OFS与ORS中,\n#"
  },
  {
    "path": "codes/shell/查找替换文本/grep.sh",
    "chars": 117,
    "preview": "#!/usr/bin/env bash\n\n# 使用 grep 命令可以用于在文件中查找指定文本\n\n# 在二进制文件中查找字符串\nfile=$1\nkeyword=$2\nstrings ${file} | grep ${keyword}\n"
  },
  {
    "path": "codes/shell/查找替换文本/regex/目录文件计数.sh",
    "chars": 264,
    "preview": "#!/usr/bin/env bash\n\n# count number of files in your PATH\n\nmypath=`echo $PATH | sed 's/:/ /g'`\ncount=0\nfor directory in "
  },
  {
    "path": "codes/shell/查找替换文本/regex/邮件验证.sh",
    "chars": 123,
    "preview": "#!/usr/bin/env bash\n\n#验证邮件\n\ngawk --re-interval '/^([a-zA-Z0-9_\\-\\.\\+]+)@([a-zA-Z0-9_\\-\\+]+)\\.([a-zA-Z]{2,5})/{print $0}'"
  },
  {
    "path": "codes/shell/查找替换文本/sed/sed文件操作.sh",
    "chars": 240,
    "preview": "#!/usr/bin/env bash\n\n#向文件写入\nsed '1,2w test1' test1\n\necho -e \"next\\n\"\n\n#从文件读取\nsed '3r ./test' ./test\n\necho -e \"next\\n\"\n\n#"
  },
  {
    "path": "codes/shell/查找替换文本/sed/sed编辑器基础.sh",
    "chars": 1486,
    "preview": "#!/usr/bin/env bash\n\n#sed编辑器基础\n\n#替换标记\nsed 's/lazy/ht/' ./test\n\necho -e \"next\\n\"\n\n#可用的替换标记\n#1.数字 表明新闻本将替换第几处模式匹配的地方\nsed '"
  },
  {
    "path": "codes/shell/查找替换文本/sed/test",
    "chars": 130,
    "preview": "This is the header line\nThis is the first data line\nThis is the data line\nThis is the second data line\nline This is the "
  },
  {
    "path": "codes/shell/查找替换文本/sed/保持空间.sh",
    "chars": 136,
    "preview": "#!/usr/bin/env bash\n\n#h将模式空间保存到保持空间\n#H将模式空间附加到保持空间\n#g将保持空间复制到模式空间\n#G将保持空间保存到模式空间\n#x交换模式空间和保持空间的内容\n\nsed -n '/first/{\nh\np\n"
  },
  {
    "path": "codes/shell/查找替换文本/sed/删除指定的空白行和删除html标签.sh",
    "chars": 230,
    "preview": "#!/usr/bin/env bash\n\n#多个空格只保留一个\n#sed '/./,/^$/!d' test\n\n#删除开头的空白行\n#sed '/./,$!d' test\n\n#删除结尾的空白行\nsed '{\n:start\n/^\\n*$/{$"
  },
  {
    "path": "codes/shell/查找替换文本/sed/在脚本中使用sed.sh",
    "chars": 102,
    "preview": "#!/usr/bin/env bash\n\n# shell wrapper for sed editor script to reverse lines\n\nsed -n '{\n1!G\nh\n$p\n}' $1\n"
  },
  {
    "path": "codes/shell/查找替换文本/sed/排除命令.sh",
    "chars": 94,
    "preview": "!/bin/bash\n\n#排除命令,使本来起作用的命令不起作用\n\nsed -n '/heade/!p' test\n\n#反转文本文件\nsed -n '{1!G ; h; $p}' test\n"
  },
  {
    "path": "codes/shell/查找替换文本/sed/模式替代.sh",
    "chars": 331,
    "preview": "#!/usr/bin/env bash\n\n#and符号,代表替换命令中的匹配模式,不管预定义模式是什么文本,都可以用and符号替换,and符号会提取匹配替换命令中指定替换模式中的所有字符串\necho \"The cat sleeps in h"
  },
  {
    "path": "codes/shell/查找替换文本/sed/测试.sh",
    "chars": 139,
    "preview": "#!/usr/bin/env bash\n\n#测试,如果测试成功,如果没有标签,sed会跳转到结尾,如果有标签,就跳转到标签,如果测试失败,则不会跳转\nsed -n '{s/first/matched/; t; s/This is the/N"
  },
  {
    "path": "codes/shell/查找替换文本/sed/给文件中的行编号.sh",
    "chars": 53,
    "preview": "#!/usr/bin/env bash\n\nsed '=' test | sed 'N; s/\\n/ /'\n"
  },
  {
    "path": "codes/shell/查找替换文本/sed/跳转.sh",
    "chars": 201,
    "preview": "#!/usr/bin/env bash\n\n#跳转到指定脚本\nsed '{/first/b jump1; s/This is the/No jump on/; :jump1; s/This is the/Jump here on/}' tes"
  },
  {
    "path": "codes/shell/查找替换文本/sed/输出末尾指定行数的数据.sh",
    "chars": 81,
    "preview": "#!/usr/bin/env bash\n\n#输出末尾10行数据\n\nsed '{\n:start\n$q\nN\n11,$D\nb start\n}' /etc/passwd\n"
  },
  {
    "path": "codes/shell/查找替换文本/sed/重定向sed输出.sh",
    "chars": 321,
    "preview": "#!/usr/bin/env bash\n\n# add commas to numbers in factorial answer\n\nfactorial=1\ncounter=1\nnumber=$1\n\nwhile [ $counter -le "
  },
  {
    "path": "codes/shell/系统管理/控制远程服务器执行指令.sh",
    "chars": 538,
    "preview": "#!/usr/bin/expect\n\nuser=\"root\"\npassword=\"root\"\n\n/usr/bin/expect << EOF\nset timeout 5\nspawn ssh -o \"StrictHostKeyChecking"
  },
  {
    "path": "codes/shell/系统管理/系统用户管理.sh",
    "chars": 376,
    "preview": "#!/usr/bin/env bash\n\n###################################################################################\n# Linux 系统用户管理\n"
  },
  {
    "path": "codes/shell/脚本函数/lib.sh",
    "chars": 216,
    "preview": "#!/usr/bin/env bash\n\nadd() {\n    echo $[ $1 + $2 ]\n}\n\nsub() {\n    echo $[ $1 - $2 ]\n}\n\nmul() {\n    echo $[ $1 * $2 ]\n}\n\n"
  }
]

// ... and 151 more files (download for full content)

About this extraction

This page contains the full source code of the dunwu/linux-tutorial GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 351 files (742.6 KB), approximately 285.2k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!