企业自建 GitLab 代码库的安装和基本配置使用
0x00 前言
在开源世界中,是没有终结的尽头!
描述:GitLab 是一个非常优秀的项目。这是一个开源项目,允许用户在自己的服务器上运行类似于 GitHub 的项目管理系统。
可以使用 GitLab 在公开发布之前开发私有项目。
官网地址:https://about.gitlab.com/
帮助文档:https://about.gitlab.com/install/
组件参考:https://docs.gitlab.com/ce/development/architecture.html
GitLab 采用传统的开源商业模式,他们有两种产品:
- 免费的开源软件,用户可以在自己的服务器上安装,以及类似于 GitHub 的托管服务。
- 免费的社区版
Gitlab CE
和付费企业版Gitlab EE
- 企业版基于社区版但附带针对企业客户的其他功能,它或多或少与 WordPress.org 或 Wordpress.com 提供的服务类似。
Gitlab优点:
- 有开源免费的版本,可以进行私有开发上传与拉取;
- 社区版具有高度可扩展性,可以在单个服务器或群集上支持 25000 个用户
- GitLab 的一些功能包括:Git 仓库管理,代码评论,问题跟踪,活动源和维基
- 它配备了 GitLab CI,用于持续集成和交付
0x01 环境安装
CentOS
Gitlab 基础要求:至少4GB的空闲RAM来运行GitLab
- 系统:CentOS Linux release 8.0.1905 (Core)GitLab 12.9.2 (ac5568eb5d8) GitLab Shell 12.0.0 GitLab Workhorse v8.25.1 GitLab APIv 4 Ruby 2.6.5p114 Rails 6.0.2 PostgreSQL 10.12 Gitaly Servers
Gitlab 安装方式:
- 官方推荐使用Omnibus快速安装(采用rpm软件包进行安装部署(国内推荐直接镜像源下载));#此处以社区版本为例 curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash sudo EXTERNAL_URL="https://gitlab.example.com" dnf install -y gitlab-ee
- 采用yum进行安装部署;
安装流程:
Step1.采用rpm进行安装社区版gitlab(替换更新源自己选择即可):
sudo dn8 install -y curl policycoreutils openssh-server wget
#可以使用 wget 的方式把 rpm 包下载下来安装
wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el8/gitlab-ce-12.9.2-ce.0.el8.x86_64.rpm
#dnf install gitlab-ce-12.9.2-ce.0.el8.x86_64.rpm
rpm -ivh gitlab-ce-12.9.2-ce.0.el8.x86_64.rpm
Step2.安装完成后显示以下则说明安装成功:
Thank you for installing GitLab!
GitLab was unable to detect a valid hostname for your instance.
Please configure a URL for your GitLab instance by setting `external_url`
configuration in /etc/gitlab/gitlab.rb file.
Then, you can start your GitLab instance by running the following command:
sudo gitlab-ctl reconfigure
Step3.修改 gitlab 默认配置
$vim /etc/gitlab/gitlab.rb
# 修改为你自己的域名或者 IP,是单引号,而且前面的 http 不要改 (并且将该域名加入到hosts中)
external_url 'http://gitlab.weiyigeek.top'
# 邮件配置,没有邮件服务器可以关闭邮件服务功能
# gitlab_rails['smtp_enable'] = false
# gitlab_rails['smtp_address'] = ""
# gitlab_rails['smtp_port'] = 587
# gitlab_rails['smtp_user_name'] = ""
# gitlab_rails['smtp_password'] = ""
# gitlab_rails['smtp_authentication'] = ""
# gitlab_rails['smtp_enable_starttls_auto'] =
# gitlab_rails['smtp_tls'] =
# gitlab_rails['gitlab_email_from'] = ''
Step4.完成修改后需要重新加载配置然后重启即可;
$ gitlab-ctl reconfigure
# [2020-04-15T10:33:44+08:00] WARN: Please install an English UTF-8 locale for Chef to use, falling back to C locale and disabling UTF-8 support. #如果看着不舒服自己设置系统语系即可
# [2020-04-15T10:33:45+08:00] WARN: Please install an English UTF-8 locale for Chef to use, falling back to C locale and disabling UTF-8 support.
# Starting Chef Client, version 14.14.29
# resolving cookbooks for run list: ["gitlab"]
# Synchronizing Cookbooks:
# - redis (0.1.0)
# - package (0.1.0)
# - postgresql (0.1.0)
# - mattermost (0.1.0)
# - consul (0.1.0)
# - letsencrypt (0.1.0)
# - gitlab (0.0.1)
# - runit (4.3.0)
# - monitoring (0.1.0)
# - praefect (0.1.0)
# - gitaly (0.1.0)
# - registry (0.1.0)
# - acme (4.1.1)
# - nginx (0.1.0)
# - crond (0.1.0)
# Running handlers:
# Running handlers complete
# Chef Client finished, 541/1460 resources updated in 03 minutes 14 seconds
# gitlab Reconfigured!
$ gitlab-ctl restart
# [2020-04-15T10:37:51+08:00] WARN: Please install an English UTF-8 locale for Chef to use, falling back to C locale and disabling UTF-8 support.
# ok: run: alertmanager: (pid 21410) 1s
# ok: run: gitaly: (pid 21422) 0s
# ok: run: gitlab-exporter: (pid 21429) 1s
# ok: run: gitlab-workhorse: (pid 21444) 0s
# ok: run: grafana: (pid 21463) 0s
# ok: run: logrotate: (pid 21474) 0s
# ok: run: nginx: (pid 21480) 0s
# ok: run: node-exporter: (pid 21563) 1s
# ok: run: postgres-exporter: (pid 21569) 0s
# ok: run: postgresql: (pid 21580) 0s
# ok: run: prometheus: (pid 21589) 0s
# ok: run: redis: (pid 21601) 0s
# ok: run: redis-exporter: (pid 21708) 0s
# ok: run: sidekiq: (pid 21716) 0s
# ok: run: unicorn: (pid 21727) 0s
Step5.如果 reconfigure 失败,则需要 systemctl enable gitlab-runsvdir && systemctl restart gitlab-runsvdir
重启一下 gitlab-runsvdir 服务
Step6.打开浏览器进行初始化账户设定密码,这个密码为 root 管理员账户的密码。设置完密码之后会自动跳转到登录页面。
应用:http://gitlab.weiyigeek.top/
账号:root
密码:WeiyiGeek #8位及以上
Step7.登录成功的界面,是不是有种疯狂的想写代码的冲动;
Step8.英文可能对英语不好的新手可能不友好,我们进行汉化(注意:高于12.3.5的版本无需汉化,直接在用户设置里面进行设置自定义语言选择简体中文
);
#停止gitlab
gitlab-ctl stop
# 获取当前安装的版本补丁
git clone https://gitlab.com/xhang/gitlab.git
cd gitlab
# 查看全部分支版本
git branch -a
gitlab_version=$(cat /opt/gitlab/embedded/service/gitlab-rails/VERSION)
# 比较汉化标签和原标签,导出patch用的diff文件
#git diff v${gitlab_version} v${gitlab_version}-zh > ../${gitlab_version}-zh.diff
git diff remotes/origin/12-3-stable remotes/origin/12-3-stable-zh > ../${gitlab_version}-zh.diff
#打补丁的时候会提示一些补丁文件不存在,一定要跳过这些文件,不然后面reconfig的时候会报错的。
patch -d /opt/gitlab/embedded/service/gitlab-rails -p1 < ../${gitlab_version}-zh.diff
#重新编译和启动
gitlab-ctl reconfigure
gitlab-ctl start
Docker
描述: 采用采用一个低权限用户进行管理docker以及利用docker部署gitlab服务;
环境说明:
$lsb_release -a
Description: Ubuntu 20.04.1 LTS
Release: 20.04
Codename: focal
$docker version
Client: Docker Engine - Community
Version: 19.03.13
API version: 1.40
Go version: go1.13.15
Git commit: 4484c46d9d
Built: Wed Sep 16 17:02:52 2020
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.13
API version: 1.40 (minimum version 1.12)
Go version: go1.13.15
Git commit: 4484c46d9d
Built: Wed Sep 16 17:01:20 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.3.7
GitCommit: 8fba4e9a7d01810a393d5d25a3621dc101981175
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683
操作流程:
# 1.新建低权限用户并将该用户加入到docker组
sudo useradd -m -g docker WeiyiGeek-gitlab && sudo passwd WeiyiGeek-gitlab
sudo gpasswd -a WeiyiGeek-gitlab docker
# 2.切换到低权限的WeiyiGeek-gitlab用户拉去最新社区版本的gitlab
WeiyiGeek-gitlab@gitlab-WeiyiGeek:~$ docker pull gitlab/gitlab-ce
# Using default tag: latest
# latest: Pulling from gitlab/gitlab-ce
# 4f53fa4d2cf0: Pull complete
# 6af7c939e38e: Pull complete
# 903d0ffd64f6: Pull complete
# 04feeed388b7: Pull complete
# 25d5e5c7360d: Pull complete
# 0cc025692f2b: Pull complete
# eac308723fda: Pull complete
# 2135ce2185ba: Pull complete
# 3d2db784a8b0: Pull complete
# d2942fac7230: Pull complete
# Digest: sha256:b7daf0c109a62e776f5f72b728a01191059a51f43b5df82c53ef997e877a784f
# Status: Downloaded newer image for gitlab/gitlab-ce:latest
# docker.io/gitlab/gitlab-ce:latest
# 3.设置持久化目录并运行gitlab-server
$ mkdir -vp ~/{config,logs,data}
# mkdir: created directory '/home/WeiyiGeek-gitlab/config'
# mkdir: created directory '/home/WeiyiGeek-gitlab/logs'
# mkdir: created directory '/home/WeiyiGeek-gitlab/data'
$ docker run -d -p 443:443 -p 80:80 -p 22:22 --name gitlab-server --restart always -v /home/WeiyiGeek-gitlab/config:/etc/gitlab -v /home/WeiyiGeek-gitlab/logs:/var/log/gitlab -v /home/WeiyiGeek-gitlab/data:/var/opt/gitlab gitlab/gitlab-ce
512c45077bafaf1c617ddd6e43f4b8a9a147ca3c8b9e8e889b14d58f151647fe
# 4.利用docker logs查看gitlab 初始化是否完成
WeiyiGeek-gitlab@gitlab-WeiyiGeek:~$ docker logs -f --tail 100 512c
==> /var/log/gitlab/puma/puma_stdout.log <==
{"timestamp":"2020-10-10T06:14:37.385Z","pid":767,"message":"PumaWorkerKiller: Consuming 3219.65625 mb with master and 4 workers."}
# 5.主机名称配置
sudo tee /etc/hosts <<'EOF'
192.168.10.222 gitlab.weiyigeek.top
EOF
PS: 配置文件地址/etc/WeiyiGeek-gitlab/config
如何配置请参考下面文章,此处不再多做叙述;
# 修改的键值对
sudo egrep -v "^#|^$" /home/WeiyiGeek-gitlab/config/gitlab.rb
[sudo] password for WeiyiGeek:
external_url 'http://gitlab.WeiyiGeek.top'
user['git_user_name'] = "Gitlab"
user['git_user_email'] = "gitlab@WeiyiGeek.top"、
gitlab_rails['gitlab_ssh_host'] = 'gitlab.WeiyiGeek.top'
gitlab_rails['gitlab_shell_ssh_port'] = 2222
gitlab_rails['gitlab_shell_git_timeout'] = 800
gitlab_rails['time_zone'] = 'Asia/Shanghai'
gitlab_rails['gitlab_email_enabled'] = true
gitlab_rails['gitlab_email_from'] = 'gitlab@WeiyiGeek.top'
gitlab_rails['gitlab_email_display_name'] = 'Gitlab'
gitlab_rails['gitlab_email_reply_to'] = 'jw@WeiyiGeek.top'
gitlab_rails['gitlab_email_subject_suffix'] = 'WeiyiGeek-IT'
gitlab_rails['object_store']['enabled'] = false
gitlab_rails['object_store']['connection'] = {}
gitlab_rails['object_store']['storage_options'] = {}
gitlab_rails['object_store']['proxy_download'] = false
gitlab_rails['object_store']['objects']['artifacts']['bucket'] = nil
gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = nil
gitlab_rails['object_store']['objects']['lfs']['bucket'] = nil
gitlab_rails['object_store']['objects']['uploads']['bucket'] = nil
gitlab_rails['object_store']['objects']['packages']['bucket'] = nil
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = nil
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = nil
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.exmail.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "gitlab@WeiyiGeek.top"
gitlab_rails['smtp_password'] = "Hm595Yb"
gitlab_rails['smtp_domain'] = "WeiyiGeek.com.top"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_tls'] = true
# 修改后重启gitlab容器即可
$ docker restart gitlab
0x02 操作说明
Gitlab相关操作及说明:
#查看Gitlab版本
cat /opt/gitlab/embedded/service/gitlab-rails/VERSION
/etc/gitlab/gitlab.rb #gitlab配置文件
/opt/gitlab #gitlab的程序安装目录
/var/opt/gitlab #gitlab目录数据目录(通过gitlab.rb修改的子模块配置文件存放的)
/var/opt/gitlab/git-data #存放仓库数据
/var/opt/gitlab/backups #默认备份目录
#Gitlab的服务构成:
gitlab-shell:用于处理Git命令和修改authorized keys列表
gitlab-workhorse:轻量级的反向代理服务器
logrotate:日志文件管理工具
nginx:静态web服务器
postgresql:数据库
redis:缓存数据库
sidekiq:用于在后台执行队列任务(异步执行)
unicorn:GitLab Rails应用是托管在这个服务器上面的。
gitlab-ctl 命令
基础命令:
#常用命令
gitlab-ctl reconfigure #生成配置并重新启动服务
gitlab-ctl start #启动所有 gitlab 组件:
gitlab-ctl status #查看当前gitlab所有服务运行状态
gitlab-ctl stop #停止gitlab服务
gitlab-ctl pg-upgrade #升级PostgreSQL最新版本
#单独启动|停止|重启某个服务
gitlab-ctl start nginx #启动nginx组件
gitlab-ctl stop postgresql #停止所有 gitlab postgresql 组件:
gitlab-ctl restart unicorn #重启相关数据连接服务
gitlab-ctl restart sidekiq #重启相关数据连接服务
gitlab-ctl restart gitlab-workhorse # 重启所有 gitlab gitlab-workhorse 组件:
#日志管理
gitlab-ctl tail #查看所有服务的日志
gitlab-ctl tail redis #实时检查redis的日志(延伸某个服务也是一样得)
gitlab-rails 命令
基础示例:
#gitlab重置密码
gitlab-rails console
> u=User.where(id:1).first #这个是管理员的,也可以用email等
> u.password = 'your_password' #密码有格式限制,我只知道8位以上否则会保存失败
> u.password_confirmation = 'your_password'
> u.save
gitlab-rake 命令
基础示例:
gitlab-rake gitlab:check SANITIZE=true --trace # 检查gitlab
gitlab-rake db:migrate # 数据库关系升级
gitlab-rake cache:clear # 清理redis缓存
0x03 基础配置
Gitlab初始化设置
0) 用户主题与语言设置
流程:右上角个人头像->settings->Preferences->主题设置|语法高亮主题|自定义语言和区域相关设置
1) 关闭Gravatar头像功能进行网络加速
Setting -> Gravatar enabled(展开Expand) -> not Checked Gravatar enabled
-> Sava Changes
2) 用户管理与注册相关设置
描述:是否用户自己进行注册以及设置密码策略和注册邮箱域名(白|黑名单)等信息,如果关闭后首页将不显示注册;
- 创建用户:
Admin Area
-> User -> New User -> 项目限制(创建得数量默认即可) ->Can create group
(企业内部建议取消) -> 创建用户 (用户邮箱将会收到一份注册邮件) - 模仿用户 impersonate: 可以模仿用户登录,不用退出再登录;
WeiyiGeek.
3) 代码推送提醒功能
描述:添加一个项目有代码提交后发邮件给指定的邮箱提醒通知,这个对于代码审核还是有帮助的,至少知道谁什么时候推送新代码了,更新了哪些内容等;
管理员登陆到gitlab界面 Admin area-> Service Templates -> Emails on push
, 勾选Active,Recipients填写本项目更新需要推送知晓的人员,多个用空格或者逗号隔开;
4) 设置ssh shell的端口
用于处理Git命令和修改authorized keys列表
gitlab_rails['gitlab_shell_ssh_port'] = 9022
5) 修改gitlab的仓库(repositories)存放目录
描述:安装好后要将仓库(repositories)放在一个大硬盘上,所以需要修改仓库对应的目录。
(注:我是先将所以的repositories删除再作以下操作的,还把 /var/opt/gitlab/git-data/repositories/用户名
目录下所有用户名下的文件全删除,目录删的只剩下空文件夹)
#查看磁盘空间大小(可以根据您自己添加的磁盘进行操作)
$df -h
/dev/mapper/cl-home 24G 954M 24G 4% /home
#新建新仓库目录
$mkdir -p /home/gitlab/git-data
#配置gitlab的数据存储位置为/home目录下
$vi /etc/gitlab/gitlab.rb
git_data_dirs({ "default" => { "path" => "/home/gitlab/git-data" } })
#重新加载配置
$sudo gitlab-ctl reconfigure
#重载后发现我们更改的仓库地址下面有数据存放了
$ls /home/gitlab/git-data/
repositories
6) 创建一个开发组
在Gitlab登录后的主页面上点击Create a group
->输入相关组信息创建即可;
邀请成员加入到组:Members
->Group members
->Invite memeber
-> 选择用户加入到刚创建的组以及角色权限;
7) 项目创建与初始化
Gitlab的git地址组成与github是一致(别告诉我您不知道): gitlab地址+用户/群组+自定义名字
Gitlab项目的可见类型有三种级别。
- Private project: 该级别是只有项目拥有者或者已经得到授权的人可以访问该项目,或者这些人是该项目组的成员。
- Internal project: 只要有用户名和密码,
可以登陆该项目所在的Gitlab服务器的
,均可访问该项目。 - public projects: 只要知道该项目的具体位置就是路径,都可以访问该项目,
它们默认的使用的是guest权限
。
比如我们在上面的开发组项目中进行创建项目操作流程如下:
1.进入开发组->New Project->设置项目名称->创建项目
2.建议添加SSH密钥到Gitlab中免密码推送与拉取git@gitlab.weiyigeek.top:newproject/secopsdev.git
:Setting -> SSH;
$ ls ~/.ssh/
id_ed25519 id_ed25519.pub id_rsa id_rsa.pub known_hosts
3.项目的初始化:
#基础设置(前提你需要下载git)
git config --global user.name "WeiyiGeek"
git config --global user.email "weiyigeek@qq.com"
#创建一个新的存储库
git clone git@gitlab.weiyigeek.top:newproject/secopsdev.git
cd secopsdev
touch README.md
git add README.md
git commit -m "add README"
#推送现有文件夹
cd existing_folder
git init
git remote add origin http://gitlab.weiyigeek.top/newproject/secopsdev.git
git add .
git commit -m "Initial commit"
#推动现有的Git存储库
cd existing_repo
git remote rename origin old-origin #将本地分支改名
git remote add origin http://gitlab.weiyigeek.top/newproject/secopsdev.git
4.需要注意默认是无法进行提交的这是由于Master主分支被保护所导致的,如果想直接对主分支进行更改而又不想创建子分支可以采用以下方式,前提是必须采用Maintainers的用户上传Master分支后进行设置
;
Project -> Settings -> Repository -> Brach (分支权限设置
) 或者 删除保护;
8) 用户项目权限控制
权限管理理解:
- (1).新建用户的时候选择一个普通权限和管理员权限之分即可
- (2).建git库的时候可以关联一个组或者一个成员
- (3).添加到组里面的人员可以设定Guest Reporter Developer Master Owner
- (4).不同git库里面的关联同一个成员可以设置不同权限
- (5).不同git库里面的关联同一个组无法设置不同权限
- (6).一个git库只能关联一个组成员
- (7).一个组成员可以被多个git库关联,且权限一样
- (8).一个成员可以被多个git库或组成员关联,且权限可以不一样
- (9).Reporter以上才有下代码权限
- (10).企业权限控制:
- 开发人员:developer权限
- 代码审核MDE:master权限
项目组&x项目权限管理:
- Project Name -> Memebers-> 用户成员与
Choose a role permission
-> 以及失效日期设置 参考官方文档网站列出了Guest,Reporter,Developer,Maintainer(Master),Owner
对应的权限,比如上面我们设置的Dev默认对保护分支是没有push权限的;
9) 广播信息设置
描述: 广播信息会显示给全部用户,可以用于通知用户系统定期维护、近期计划升级等信息,在用户登陆界面以及用户提交代码的时候会有显示
。
Area Admin -> Messages -> Broadcast Information (设置即可)
Gitlab数据备份恢复
描述:GitLab作为公司项目代码的版本管理系统,数据非常重要所以必须做好备份。
Gitlab提供了两种备份:
- 本地备份
- 远程备份
本地备份
#1.GitLab备份的默认目录是
/var/opt/gitlab/backups
#2.修改改备份目录
$vim /etc/gitlab/gitlab.rb
gitlab_rails['backup_path'] = '/home/backups'
#备份保留7天
gitlab_rails['backup_keep_time'] = 604800
#3.修改配置后重载配置
$gitlab-ctl reconfigure
#4.执行备份命令
$gitlab-rake gitlab:backup:create
# 2020-04-16 09:44:52 +0800 -- Dumping database ...
# Dumping PostgreSQL database gitlabhq_production ... [DONE]
# 2020-04-16 09:44:53 +0800 -- done
# 2020-04-16 09:44:53 +0800 -- Dumping repositories ...
# 2020-04-16 09:44:53 +0800 -- done
# 2020-04-16 09:44:53 +0800 -- Dumping uploads ...
# 2020-04-16 09:44:53 +0800 -- done
# 2020-04-16 09:44:53 +0800 -- Dumping builds ...
# 2020-04-16 09:44:53 +0800 -- done
# 2020-04-16 09:44:53 +0800 -- Dumping artifacts ...
# 2020-04-16 09:44:53 +0800 -- done
# 2020-04-16 09:44:53 +0800 -- Dumping pages ...
# 2020-04-16 09:44:53 +0800 -- done
# 2020-04-16 09:44:53 +0800 -- Dumping lfs objects ...
# 2020-04-16 09:44:53 +0800 -- done
# 2020-04-16 09:44:53 +0800 -- Dumping container registry images ...
# 2020-04-16 09:44:53 +0800 -- [DISABLED]
# Creating backup archive: 1587001493_2020_04_16_12.9.2_gitlab_backup.tar ... done
# Uploading backup archive to remote storage ... skipped
#5.查看备份文件,压缩包包括GitLab整个的完整部分,大概格式xxxxxxxx_gitlab_backup.tar
$ls /var/opt/gitlab/backups
1587001493_2020_04_16_12.9.2_gitlab_backup.tar
补充说明:
- 通过任务计划crontab 实现自动备份#输入命令crontab -e sudo crontab -e 0 2 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create #重启服务 systemctl restart crond
- 值得注意的是由于
gitlab.rb and gitlab-secrets.json
包含敏感数据,采用上面备份的形式不能将它们进行备份,只能通过手动备份
的方式;
远程备份
描述:实际上就是在gitlab服务器上添加备份服务器的pub公钥,然后备份服务器访问Gitlab服务器进行拉取,当然您也可以采用rsync进行备份;
#假设环境如下:
#备份服务器: 192.168.1.2
#GitLab服务器: 192.168.1.250
#1.备份服务器创建authorized_keys文件
mkdir -p /root/.ssh
touch /root/.ssh/authorized_keys
chmod 400 /root/.ssh/authorized_keys
#2.Gitlab服务器生成rsa公钥并将证书上传到备份服务器(实际环境中建议最小权限用户)
$ssh-keygen -t rsa -C "gitlab@weiyigeek.top"
# Enter file in which to save the key (/root/.ssh/id_rsa): 报错路径
# Enter passphrase (empty for no passphrase): 公钥密码
# Enter same passphrase again: 验证密码
# Your public key has been saved in /root/.ssh/id_rsa.pub. #保存路径
# The key fingerprint is:
# SHA256:YahioDs7XZ9No********RS9jWX1NNXo04i4ZHOLY WeiyiGeek@weiyigeek.top
# The key's randomart image is:
# +---[RSA 2048]----+
# | . . ++|
# | .+ . o o.+|
# |. o.oo= . + .|
# |.. ..=.E.+ + |
# |o o..+ oS= . . |
# |.=+.+ o . . |
# |+*.. = + |
# |oo= o o . |
# |.o.+ |
# +----[SHA256]-----+
$ls /root/.ssh/
id_rsa id_rsa.pub
$scp /root/.ssh/id_rsa.pub root@192.168.1.2:/root/.ssh/
#3.备份服务器将id_rsa.pub文件内容追加到authorized_keys 文件中,并且修改authorized_keys文件的权限
$cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
#4.gitlab备份脚本(主要执行权限呼吁)将备份文件拷贝到服务器端
$cat > /home/gitlab/auto_backup_to_remote.sh<<'END'
DATE=`date +"%Y_%m_%d"`
BackupIP=192.168.1.2
BackupUser=root
BackupPATH=/var/opt/gitlab/backups
#删除本地7天前得备份
find ${BackupPATH} -type f -mtime +7 -name '*.tar' -exec rm {} ;
#如果不需要备份文件您也可以备份仓房目录
find ${BackupPATH} -name *${DATE}* -exec scp -r {} ${root}@${BackupIP}:/tmp/ ;
END
$chmod +x /home/gitlab/auto_backup_to_remote.sh
#5.添加定时计划(每天凌晨1点执行),重启crond服务
cat >> /etc/crontab <<END
0 1 * * * /home/gitlab/auto_backup_to_remote.sh
END
systemctl restart crond
Gitlab数据恢复
比如:上面我们得备份:/var/opt/gitlab/backups/1587001493_2020_04_16_12.9.2_gitlab_backup.tar
;
操作流程如下:
#停止相关数据连接服务(保证数据库没有新的连接不会有写数据情况)
gitlab-ctl stop unicorn
gitlab-ctl stop sidekiq
#指定恢复文件会自动去备份目录找格式:1587001493_2020_04_16_12.9.2
cd /var/opt/gitlab/backups/ && chmod -R 777 *
gitlab-rake gitlab:backup:restore BACKUP=1587001493_2020_04_16_12.9.2
#启动Gitlab
gitlab-ctl restart
Gitlab添加发信邮箱
邮件找回密码:
1)因为gitlab一直都在运行着,所以要修改前记录备份一下配置文件;
cp /etc/gitlab/gitlab.rb{,.bak}
2)修改配置文件:/etc/gitlab/gitlab.rb 这里使用公司的企业邮箱来发邮件;
$egrep -v "^$|^#" /etc/gitlab/gitlab.rb
external_url 'http://gitlab.weiyigeek.top'
gitlab_rails['time_zone'] = 'Asia/Shanghai'
gitlab_rails['gitlab_email_enabled'] = true
gitlab_rails['gitlab_email_from'] = 'public@weiyigeek.top'
gitlab_rails['gitlab_email_display_name'] = 'Gitlab CE'
gitlab_rails['gitlab_email_reply_to'] = 'gitlab@weiyigeek.top'
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.exmail.qq.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "public@weiyigeek.top"
gitlab_rails['smtp_password'] = "邮箱密码"
gitlab_rails['smtp_domain'] = "weiyigeek.top"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = true
user['git_user_email'] = "public@weiyigeek.top"
3)保存修改,更新配置;
#只是把修改过的配置文件信息,刷新到配置文件中
gitlab-ctl reconfigure
其实上面修改一个配置文件gitlab.rb 它里面的配置会被此命令调用编写成多个配置文件到安装目录下:/var/opt/gitlab/gitlab-rails/etc/
$ls /var/opt/gitlab/gitlab-rails/etc/
database.yml gitlab_shell_secret gitlab.yml resque.yml smtp_settings.rb #也可以直接修改
gitlab_pages_secret gitlab_workhorse_secret rack_attack.rb secrets.yml unicorn.rb
如果直接修改smtp_settings.rb
文件就只要重启一下gitlab-ctl restart
即可。
4)控制台查看配置与测试发信
$gitlab-rails console
--------------------------------------------------------------------------------
GitLab: 12.9.2 (ac5568eb5d8) FOSS
GitLab Shell: 12.0.0
PostgreSQL: 10.12
--------------------------------------------------------------------------------
Loading production environment (Rails 6.0.2)
irb(main):001:0> ActionMailer::Base.delivery_method
=> :smtp
irb(main):002:0> ActionMailer::Base.smtp_settings
=> {:authentication=>:login, :address=>"smtp.exmail.qq.com", :port=>465, :user_name=>"public@weiyigeek.top", :password=>"Pa****20", :domain=>"weiyigeek.top", :enable_starttls_auto=>true, :tls=>true, :ca_file=>"/opt/gitlab/embedded/ssl/certs/cacert.pem"}
irb(main):003:0> Notify.test_email('291238737@qq.com', 'GitLab测试邮件', 'GitLab 页面信息').deliver_now
Notify#test_email: processed outbound mail in 2.0ms
Delivered mail 5e9708455a809_6b023fce629dd99085b8@Developement.mail (1543.7ms)
Date: Wed, 15 Apr 2020 21:12:37 +0800
From: Gitlab CE <public@weiyigeek.top>
Reply-To: Gitlab CE <noreply@gitlab.weiyigeek.top>
完成上面操作后,回到登陆页面,选择Forgot your password? 输入你帐号的邮箱地址即可收到邮件,根据邮件地址修改新密码即可;
补充说明:
- 在某些ECS专有网络主机上配置了一个gitlab仓库,因为默认这些专有网络的ECS主机都是禁用了25端口的,所以这个gitlab.rb的配置就有做相应的改变,使用465协议。#只修改以下两行即可,修改完要更新配置 gitlab_rails['smtp_port'] = 25 gitlab_rails['smtp_tls'] = true
Gitlab添加LDAP认证
LDAP配置说明:http://gitlab.weiyigeek.top/help/administration/auth/ldap
Step1.修改gitlab配置文件设置连接LDAP服务器参数即DN于bindPass
vim /etc/gitlab/gitlab.rb
gitlab_rails['ldap_enabled'] = true
# gitlab_rails['prevent_ldap_sign_in'] = false
###! **remember to close this block with 'EOS' below**
gitlab_rails['ldap_servers'] = YAML.load <<-'EOS'
main: # 'main' is the GitLab 'provider ID' of this LDAP server
label: 'LDAP'
host: '10.10.107.245'
port: 389
timeout: 10
uid: 'uid'
bind_dn: 'cn=admin,dc=WeiyiGeek,dc=com,dc=cn'
password: 'WeiyiGeek'
encryption: 'plain' # "start_tls" or "simple_tls" or "plain"
verify_certificates: false
smartcard_auth: false
active_directory: true
allow_username_or_email_login: true
lowercase_usernames: false
block_auto_created_users: false
base: 'dc=WeiyiGeek,dc=com,dc=cn'
#user_filter: '(&(objectclass=inetOrgPerson)(memberof=cn=gitlab,ou=Group,dc=WeiyiGeek,dc=com,dc=cn))'
attribute:
username: ['uid']
email: ['mail']
name: 'cn'
first_name: ['sn']
EOS
Step2.LDAP建立groupOfUniqueNames属性
得用户组以及绑定用户;
dn: cn=gitlab,ou=Group,dc=WeiyiGeek,dc=com,dc=cn
uniqueMember: uid=gituser,ou=People,dc=WeiyiGeek,dc=com,dc=cn
dn: uid=gituser,ou=People,dc=WeiyiGeek,dc=com,dc=cn
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
loginShell: /bin/bash
homeDirectory: /home/gituser
userPassword:: e1NTSEF9UGVyM21xc1dJcnV3K1d2bWRiVmVpd3RWZHVVeVN6Tks=
uid: gituser
cn: gituser
uidNumber: 10000
gidNumber: 10000
sn: gituser
mail: gituser@WeiyiGeek.com.cn
Step3.登陆测试如果LDAP用户不存在或者filter的条目不存在会报错Could not authenticate you from Ldapmain because "Invalid credentials for jenkuser".
Step4.登陆成功界面如下:
0x04 入坑解决
(0) 用户pull与push代码到gitlab常见错误
- 错误1:
The requested URL returned error: 403
To gitlab.weiyigeek.top:newproject/secopsdev.git ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'git@gitlab.weiyigeek.top:newproject/secopsdev.git'#最终主分支以及dev分支都测试上次成功 remote: To gitlab.weiyigeek.top:newproject/secopsdev.git * [new branch] dev -> dev Branch 'dev' set up to track remote branch 'dev' from 'origin'. - 原因:表示我们没有权限来pull/push相关代码需要修改相关gitlab账号的权限为
Development或者Maintianer
; - 错误2:
- 原因:由于上传代码的gitlab用户权限为开发者而默认创建的是私有的项目,默认是对master分支开启了保护机制,需要对其项目的Branch分支设置
Allowed to merge | Allowed to push
为Development+Maintiner;
(1) gitlab密码忘记找回重置方法
- 方式1:通过gitlab-rails进行重置$gitlab-rails console Loading production environment (Rails 6.0.2) > u=User.where(id:1).first #这个是管理员的,也可以用email等 > u.password = 'your_password' #密码有格式限制,我只知道8位以上否则会保存失败 > u.password_confirmation = 'your_password' > u.save
- 方式2:通过初始化设置邮件进行找回管理员或者在本地 postfix 中查看未发送得邮件,此处以root用户的admin@example.com为例,一般默认都没改(只是一种方式实际中没多大意义);
此处假设服务不能链接到外网之中(为了复现下列操作);
#(1)查看无法发送出去的邮件队列
$postqueue -p
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
#因为不存在此地址就无法发送出去,只能停留在邮件的列队中。
908DCCAC62 6871 Wed Apr 15 19:54:32 gitlab@gitlab.weiyigeek.top #(实际就是我们找回密码邮件)
(Host or domain name not found. Name service error for name=example.com type=MX: Host not found, try again)
admin@example.com
#(2)邮件队列存储位置
$postconf -d | grep queue_directory #默认情况下是没有修改的
queue_directory = /var/spool/postfix
#(3)进到目录下,查找上面那封邮件的队列ID号
$find /var/spool/postfix/ -name 908DCCAC62
/var/spool/postfix/defer/9/908DCCAC62
/var/spool/postfix/deferred/9/908DCCAC62
# (4) 利用postfix自带的工具查看邮件的内容,找到修改密码的地
$postcat /var/spool/postfix/deferred/9/908DCCAC62
*** ENVELOPE RECORDS /var/spool/postfix/deferred/9/908DCCAC62 ***
message_size: 6871 274 1 0 6871 0
message_arrival_time: Wed Apr 15 19:54:32 2020
create_time: Wed Apr 15 19:54:32 2020
named_attribute: rewrite_context=local
sender: gitlab@gitlab.weiyigeek.top
named_attribute: dsn_orig_rcpt=rfc822;admin@example.com
original_recipient: admin@example.com
.....
If you did not perform this request, you can safely ignore this email.
Otherwise, click the link below to complete the process:
#找到如下密码修改连接,并将其复制出来到浏览器中重置密码
http://gitlab.weiyigeek.top/users/password/edit?reset_password_token=gd9MyL7FaSt5R2F3_qA_
(2)GitLab数据库引起的502错误问题及解决方案
描述:打开GitLab的主页地址http:/gitlab.weiyigeek.top/报错502,重启或检查状态发现都正常sudo gitlab-ctl status
,并且检查了端口号并没被占用,检查刷新配置gitlab-ctl reconfigure
发现了错误;
错误信息如下:
#gitlab-ctl reconfigure
Running handlers:
There was an error running gitlab-ctl reconfigure:
bash[migrate gitlab-rails database] (gitlab::database_migrations line 51) had an error: Mixlib::ShellOut::ShellCommandFailed: Expected process to exit with [0], but received '1'
---- Begin output of "bash" "/tmp/chef-script20190308-65247-12ck9rp" ----
STDOUT: rake aborted!
PG::ConnectionBad: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/opt/gitlab/postgresql/.s.PGSQL.5432"?
/opt/gitlab/embedded/service/gitlab-rails/lib/tasks/gitlab/db.rake:52:in `block (3 levels) in <top (required)>
/opt/gitlab/embedded/bin/bundle:23:in `load'
/opt/gitlab/embedded/bin/bundle:23:in `<main>'
Tasks: TOP => gitlab:db:configure
(See full trace by running task with --trace)
STDERR:
---- End output of "bash" "/tmp/chef-script20190308-65247-12ck9rp" ----
Ran "bash" "/tmp/chef-script20190308-65247-12ck9rp" returned 1
#gitlab-ctl tail
(3) gitlab-ce版本升级记录
我们为了保证数据安全,一步步来慢慢升级,使用官方的源可能比较慢,可以使用国内的源(采用Omnibus方式进行升级直接rpm包部署):https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum
升级方法:先升级到当前大版本最后一版(这里是我的建议,一般差不多最后几版就可以了),接下来就是跨大版本的升级,先从大版本的低版升级,再到最后版本升级,以此类推; 因为我中间尝试过直接跨太多个版本升级,出现过异常,其实主要是数据库的数据导入备份问题,如果新版本跟旧版相关太大的话就会报错了。
比如我的升级过程很长,同时也做了简单的测试
#升级版本
8.3.1-->8.3.7-->8.8.5-->8.17.4-->9.5.6-->10.0.6-->10.8.5-->11.0.3
#停止服务
gitlab-ctl stop unicorn
gitlab-ctl stop sidekiq
gitlab-ctl stop nginx
#创建数据备份,防止更新失败(非常重要)
gitlab-rake gitlab:backup:create
#安装升级包
#yum update gitlab-ce # 升级GitLab-ce 版本(不建议采用此种方式)
rpm -Uvh gitlab-7.4.2_omnibus-1.el6.x86_64.rpm
#重新加载配置&重启Gitlab服务
gitlab-ctl reconfigure
gitlab-ctl restart
比如:项目备份的数据的是否有异常,用户信息,响应速度等等,个人认为还是比较靠普的。
其实只要我们之前有升级过就不会现在这样了,一下子从这么低的版本升级上来。一般建议保持在相同的大版本号就好了。太新可能也会有Bug,太旧了也会有很多历史遗留的问题。
升级完成后你会发现多了好几个进程。可能会对系统硬件要求更高了,比如内存会要求更高了。
建议:如果非必要的功能需求,只是简单的要一个代码仓库的话,个人建立使用在11.x.-12.3.x
之间也不错了。
(4) gitlab-rails database初始化失败
环境说明
Centos7: 3.10.0-327.el7.x86_64
gitlab版本:原来是8.8.5版本现升级到较新的版本;
问题:在同一台Centos7机器上卸载了旧版本的gitlab后,接着又重新安装新版本的gitlab-ce 在安装完后修改配置,初始化配置时出现以下错误:
Running handlers:
There was an error running gitlab-ctl reconfigure:
bash[migrate gitlab-rails database] (gitlab::database_migrations line 49) had an error: Mixlib::ShellOut::ShellCommandFailed: Expected process to exit with [0], but received '1'
---- Begin output of "bash" "/tmp/chef-script20190628-7065-vx17en" ----
STDOUT: rake aborted!
PG::ConnectionBad: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/opt/gitlab/postgresql/.s.PGSQL.5432"?
/opt/gitlab/embedded/service/gitlab-rails/lib/tasks/gitlab/db.rake:49:in `block (3 levels) in <top (required)>'
/opt/gitlab/embedded/bin/bundle:23:in `load'
/opt/gitlab/embedded/bin/bundle:23:in `<main>'
Tasks: TOP => gitlab:db:configure
(See full trace by running task with --trace)
STDERR:
---- End output of "bash" "/tmp/chef-script20190628-7065-vx17en" ----
Ran "bash" "/tmp/chef-script20190628-7065-vx17en" returned 1
原因:因为在卸载旧版本的时候没有把旧的数据删除,所以直接安装时,程序检测到配置文件,数据文件时就会跳过没有覆盖,新版本使用旧版本的数据文件因为版本相差太多了就会无法识别导致。
解决方法:卸载完旧版本后,记得删除旧的安装数据配置文件,安装目录,数据目录等
,重新安装新版的gitlab-ce即可正常启动。
rm -rf /var/opt/gitlab/ /opt/gitlab/ /etc/gitlab/
(5) Gitlab的数据库postgresql更新帐号信息
问题描述:由于内部的Ldap认证服务器硬盘坏掉了,导致在上面跑的Ldap服务无法对Jenkins和Gitlab平台做集中认证了,导致在Gitlab上的帐号无法登陆到平台上,也就无法提交拉取代码了。
解决思路:
- 方法一、重新配置一个Ldap服务把之前的数据库导进来,迁移到新的机器上然后修改Gitlab的认证服务地址。
- 方法二、直接修改Gitlab的数据库,对帐号的认证方式修改。
此处选择方式2进行操作其流程如下:
- Step1.修改gitlab的数据库配置,开启远程访问(默认本机访问)#1.修改配置文件添加最后两行 egrep -v "^#|^$" /var/opt/gitlab/postgresql/data/pg_hba.conf local all all peer map=gitlab host all all 127.0.0.1/32 trust host all all 0.0.0.0/0 trust #2.修改postgresql配置文件将listen_addresses把它改成*号 $vim /var/opt/gitlab/postgresql/data/postgresql.conf #------------------------------------------------------------------------------ # CONNECTIONS AND AUTHENTICATION #------------------------------------------------------------------------------ # - Connection Settings - listen_addresses = '*' # what IP address(es) to listen on; # comma-separated list of addresses; # defaults to 'localhost', '*' = all # (change requires restart) port = 5432 # (change requires restart) max_connections = 200 # (change requires restart) # Note: Increasing max_connections costs ~400 bytes of shared memory per # connection slot, plus lock space (see max_locks_per_transaction). #superuser_reserved_connections = 3 # (change requires restart) unix_socket_directories = '/var/opt/gitlab/postgresql' # (change requires restart) #3.重启postgresql服务 gitlab-ctl restart postgresql #4.使用Navicat工具连postgresql接数据库,下边的初始数据库gitlabhq_production和用户名都是默认的,密码为空
连接上后找到对应的identities表修改对应的字段,其实就是把字段中的user_id修改掉,我这里做法就是把用户的user_id改成了负数,这样在Ldap认证时就找不到了,从而走标准认证(这是在不重启Gitlab的情况下进行)。
补充说明:
- 更新后如果用户还存在登陆不了的问题,这时候可以让用户自己去Web端登陆gitlab,选择忘记密码,通过忘记密码来重新设置一个密码。(前提是你实现了密码找回功能)
- 完成所有操作后记得要把远程的配置注释掉或者删除了,然后重启postgresql服务即可。
0x05 脚本附录
GitLab一键安装配置脚本
#!/bin/bash
#Desc: Gitlab代码服务器自动化部署
#Author:WeiyiGeek
#SupportOS:CentOS7 / CentOS8
GITLAB_BASEDOMAIN=weiyigeek.top
GITLAB_VERSION=12.9.2
GITlABOS7=gitlab-ce-${GITLAB_VERSION}-ce.0.el7.x86_64.rpm
GITlABOS8=gitlab-ce-${GITLAB_VERSION}-ce.0.el8.x86_64.rpm
GITLABRUNNER_VERSION=12.9.0-1
GITLABRUNNER_NAME=gitlab-runner-${GITLABRUNNER_VERSION}.x86_64.rpm
CheckOSVersion=$(uname -r | grep -c el8)
## [镜像源设置]
function repoChange(){
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.$(date +"%Y%m%d").backup
if [ $CheckOSVersion -eq 1 ];then
# CentOS8 源
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo
# 安装 epel 配置包并地址替换为阿里云镜像站地址
dnf install -y https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm
sed -i 's|^#baseurl=https://download.fedoraproject.org/pub|baseurl=https://mirrors.aliyun.com|' /etc/yum.repos.d/epel*
sed -i 's|^metalink|#metalink|' /etc/yum.repos.d/epel*
dnf clean all
dnf makecache
else
# CentOS7 源
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
#添加信任 GitLab 里的 GPG 公钥
sudo cat > /etc/yum.repos.d/gitlab-ce.repo <<EOF
[gitlab-ce]
name=Gitlab CE Repository
baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/
gpgcheck=0
enabled=1
gpgkey=https://packages.gitlab.com/gpg.key
EOF
yum clean all
yum makecache
fi
}
#[yum 方式安装]
function yumInstall(){
# 查看可用的版本neng'b
yum list gitlab-ce --showduplicates
# 默认安装最新的版本
yum install -y gitlab-ce
# 安装指定版本 12.3.5
# yum install gitlab-ce-12.3.5-ce.0.el7.x86_64.rpm
}
#[rpm 方式安装-推荐方式]
function OmnibusInstall(){
if [ $CheckOSVersion -eq 1 ];then
wget -O $GITlABOS8 https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el8/${GITlABOS8}
rpm -i $GITlABOS8
else
wget -O $GITlABOS7 https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/${GITlABOS7}
rpm -i $GITlABOS7
fi
}
function gitlabSetting(){
sed -i "s#example.com#${GITLAB_BASEDOMAIN}#g" /etc/gitlab/gitlab.rb
echo "127.0.0.1 gitlab.${GITLAB_BASEDOMAIN}" > /etc/hosts
}
function useage(){
echo -e "e[32m# Description: Gitlab 自动化安装部署脚本"
echo -e "usage: $0 [rpm|yum] #指定rpm安装还是yum安装"
echo -e "Author:WeiyiGeeke[0m"
}
#[低于 12.3.x 版本的才进行设置]
function Chinesization(){
#停止gitlab
gitlab-ctl stop
#获取当前安装的版本补丁
git clone https://gitlab.com/xhang/gitlab.git
cd gitlab
gitlab_version=$(cat /opt/gitlab/embedded/service/gitlab-rails/VERSION)
# 生成对应版本补丁文件
git diff remotes/origin/12-3-stable remotes/origin/12-3-stable-zh > ../${gitlab_version}-zh.diff
# 打补丁的时候会提示一些补丁文件不存在,一定要跳过这些文件,不然后面reconfig的时候会报错的。
patch -d /opt/gitlab/embedded/service/gitlab-rails -p1 < ../${gitlab_version}-zh.diff
gitlab-ctl reconfigure
gitlab-ctl restart
}
## [安装配置脚本入口函数]
function main(){
#关闭Sellinux
echo "当前Selinux: $(getenforce)"
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
echo "设置Selinux: $(getenforce)"
#环境依赖安装
repoChange
sudo yum install -y curl policycoreutils openssh-server wget postfix git htop ncdu net-tools
systemctl enable postfix
systemctl start postfix
#防护墙设置
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo systemctl reload firewalld
#选择安装方式
if [ $1 == "rpm" ];then
OmnibusInstall
elif [ $1 == "yum" ];then
yumInstall
else
usage
fi
gitlabSetting
gitlab-ctl reconfigure
gitlab-ctl start
gitlab-ctl status
}
#[参数验证]
if [ $# -ne 1 ];then
usage
else
main $1
fi
原博客地址: https://weiyigeek.top/2019/7/98.html
WeiyiGeek Blog - 为了能到远方,脚下的每一步都不能少。
本文章来源 Blog 站点(友链交换请邮我哟
):
- https://weiyigeek.top # 国内访问较慢
- https://blog.weiyigeek.top # 更新频繁
- https://weiyigeek.gitee.io # 国内访问快可能会有更新不及时得情况
推荐阅读
-
企业自建 GitLab 代码库的安装和基本配置使用
-
企业自建GitLab代码仓库安装与基础配置使用
-
F#探险之旅(二):函数式编程(上)-函数式编程范式简介 F#主要支持三种编程范式:函数式编程(Functional Programming,FP)、命令式编程(Imperative Programming)和面向对象(Object-Oriented,OO)的编程。回顾它们的历史,FP是最早的一种范式,第一种FP语言是IPL,产生于1955年,大约在Fortran一年之前。第二种FP语言是Lisp,产生于1958,早于Cobol一年。Fortan和Cobol都是命令式编程语言,它们在科学和商业领域的迅速成功使得命令式编程在30多年的时间里独领风骚。而产生于1970年代的面向对象编程则不断成熟,至今已是最流行的编程范式。有道是“*代有语言出,各领风骚数十年”。 尽管强大的FP语言(SML,Ocaml,Haskell及Clean等)和类FP语言(APL和Lisp是现实世界中最成功的两个)在1950年代就不断发展,FP仍停留在学院派的“象牙塔”里;而命令式编程和面向对象编程则分别凭着在商业领域和企业级应用的需要占据领先。今天,FP的潜力终被认识——它是用来解决更复杂的问题的(当然更简单的问题也不在话下)。 纯粹的FP将程序看作是接受参数并返回值的函数的集合,它不允许有副作用(side effect,即改变了状态),使用递归而不是循环进行迭代。FP中的函数很像数学中的函数,它们都不改变程序的状态。举个简单的例子,一旦将一个值赋给一个标识符,它就不会改变了,函数不改变参数的值,返回值是全新的值。 FP的数学基础使得它很是优雅,FP的程序看起来往往简洁、漂亮。但它无状态和递归的天性使得它在处理很多通用的编程任务时没有其它的编程范式来得方便。但对F#来说这不是问题,它的优势之一就是融合了多种编程范式,允许开发人员按照需要采用最好的范式。 关于FP的更多内容建议阅读一下这篇文章:Why Functional Programming Matters(中文版)。F#中的函数式编程 从现在开始,我将对F#中FP相关的主要语言结构逐一进行介绍。标识符(Identifier) 在F#中,我们通过标识符给值(value)取名字,这样就可以在后面的程序中引用它。通过关键字let定义标识符,如: let x = 42 这看起来像命令式编程语言中的赋值语句,两者有着关键的不同。在纯粹的FP中,一旦值赋给了标识符就不能改变了,这也是把它称为标识符而非变量(variable)的原因。另外,在某些条件下,我们可以重定义标识符;在F#的命令式编程范式下,在某些条件下标识符的值是可以修改的。 标识符也可用于引用函数,在F#中函数本质上也是值。也就是说,F#中没有真正的函数名和参数名的概念,它们都是标识符。定义函数的方式与定义值是类似的,只是会有额外的标识符表示参数: let add x y = x + y 这里共有三个标识符,add表示函数名,x和y表示它的参数。关键字和保留字关键字是指语言中一些标记,它们被编译器保留作特殊之用。在F#中,不能用作标识符或类型的名称(后面会讨论“定义类型”)。它们是: abstract and as asr assert begin class default delegate do donedowncast downto elif else end exception extern false finally forfun function if in inherit inline interface internal land lazy letlor lsr lxor match member mod module mutable namespace new nullof open or override private public rec return sig static structthen to true try type upcast use val void when while with yield 保留字是指当前还不是关键字,但被F#保留做将来之用。可以用它们来定义标识符或类型名称,但编译器会报告一个警告。如果你在意程序与未来版本编译器的兼容性,最好不要使用。它们是: atomic break checked component const constraint constructor continue eager event external fixed functor global include method mixinobject parallel process protected pure sealed trait virtual volatile 文字值(Literals) 文字值表示常数值,在构建计算代码块时很有用,F#提供了丰富的文字值集。与C#类似,这些文字值包括了常见的字符串、字符、布尔值、整型数、浮点数等,在此不再赘述,详细信息请查看F#手册。 与C#一样,F#中的字符串常量表示也有两种方式。一是常规字符串(regular string),其中可包含转义字符;二是逐字字符串(verbatim string),其中的(")被看作是常规的字符,而两个双引号作为双引号的转义表示。下面这个简单的例子演示了常见的文字常量表示: let message = "Hello World"r"n!" // 常规字符串let dir = @"C:"FS"FP" // 逐字字符串let bytes = "bytes"B // byte 数组let xA = 0xFFy // sbyte, 16进制表示let xB = 0o777un // unsigned native-sized integer,8进制表示let print x = printfn "%A" xlet main = print message; print dir; print bytes; print xA; print xB; main Printf函数通过F#的反射机制和.NET的ToString方法来解析“%A”模式,适用于任何类型的值,也可以通过F#中的print_any和print_to_string函数来完成类似的功能。值和函数(Values and Functions) 在F#中函数也是值,F#处理它们的语法也是类似的。 let n = 10let add a b = a + blet addFour = add 4let result = addFour n printfn "result = %i" result 可以看到定义值n和函数add的语法很类似,只不过add还有两个参数。对于add来说a + b的值自动作为其返回值,也就是说在F#中我们不需要显式地为函数定义返回值。对于函数addFour来说,它定义在add的基础上,它只向add传递了一个参数,这样对于不同的参数addFour将返回不同的值。考虑数学中的函数概念,F(x, y) = x + y,G(y) = F(4, y),实际上G(y) = 4 + y,G也是一个函数,它接收一个参数,这个地方是不是很类似?这种只向函数传递部分参数的特性称为函数的柯里化(curried function)。 当然对某些函数来说,传递部分参数是无意义的,此时需要强制提供所有参数,可是将参数括起来,将它们转换为元组(tuple)。下面的例子将不能编译通过: let sub(a, b) = a - blet subFour = sub 4 必须为sub提供两个参数,如sub(4, 5),这样就很像C#中的方法调用了。 对于这两种方式来说,前者具有更高的灵活性,一般可优先考虑。 如果函数的计算过程中需要定义一些中间值,我们应当将这些行进行缩进: let halfWay a b = let dif = b - a let mid = dif / 2 mid + a 需要注意的是,缩进时要用空格而不是Tab,如果你不想每次都按几次空格键,可以在VS中设置,将Tab字符自动转换为空格;虽然缩进的字符数没有限制,但一般建议用4个空格。而且此时一定要用在文件开头添加#light指令。作用域(Scope)作用域是编程语言中的一个重要的概念,它表示在何处可以访问(使用)一个标识符或类型。所有标识符,不管是函数还是值,其作用域都从其声明处开始,结束自其所处的代码块。对于一个处于最顶层的标识符而言,一旦为其赋值,它的值就不能修改或重定义了。标识符在定义之后才能使用,这意味着在定义过程中不能使用自身的值。 let defineMessage = let message = "Help me" print_endline message // error 对于在函数内部定义的标识符,一般而言,它们的作用域会到函数的结束处。 但可使用let关键字重定义它们,有时这会很有用,对于某些函数来说,计算过程涉及多个中间值,因为值是不可修改的,所以我们就需要定义多个标识符,这就要求我们去维护这些标识符的名称,其实是没必要的,这时可以使用重定义标识符。但这并不同于可以修改标识符的值。你甚至可以修改标识符的类型,但F#仍能确保类型安全。所谓类型安全,其基本意义是F#会避免对值的错误操作,比如我们不能像对待字符串那样对待整数。这个跟C#也是类似的。 let changeType = let x = 1 let x = "change me" let x = x + 1 print_string x 在本例的函数中,第一行和第二行都没问题,第三行就有问题了,在重定义x的时候,赋给它的值是x + 1,而x是字符串,与1相加在F#中是非法的。 另外,如果在嵌套函数中重定义标识符就更有趣了。 let printMessages = let message = "fun value" printfn "%s" message; let innerFun = let message = "inner fun value" printfn "%s" message innerFun printfn "%s" message printMessages 打印结果: fun value inner fun valuefun value 最后一次不是inner fun value,因为在innerFun仅仅将值重新绑定而不是赋值,其有效范围仅仅在innerFun内部。递归(Recursion)递归是编程中的一个极为重要的概念,它表示函数通过自身进行定义,亦即在定义处调用自身。在FP中常用于表达命令式编程的循环。很多人认为使用递归表示的算法要比循环更易理解。 使用rec关键字进行递归函数的定义。看下面的计算阶乘的函数: let rec factorial x = match x with | x when x < 0 -> failwith "value must be greater than or equal to 0" | 0 -> 1 | x -> x * factorial(x - 1) 这里使用了模式匹配(F#的一个很棒的特性),其C#版本为: public static long Factorial(int n) { if (n < 0) { throw new ArgumentOutOfRangeException("value must be greater than or equal to 0"); } if (n == 0) { return 1; } return n * Factorial (n - 1); } 递归在解决阶乘、Fibonacci数列这样的问题时尤为适合。但使用的时候要当心,可能会写出不能终止的递归。匿名函数(Anonymous Function) 定义函数的时候F#提供了第二种方式:使用关键字fun。有时我们没必要给函数起名,这种函数就是所谓的匿名函数,有时称为lambda函数,这也是C#3.0的一个新特性。比如有的函数仅仅作为一个参数传给另一个函数,通常就不需要起名。在后面的“列表”一节中你会看到这样的例子。除了fun,我们还可以使用function关键字定义匿名函数,它们的区别在于后者可以使用模式匹配(本文后面将做介绍)特性。看下面的例子: let x = (fun x y -> x + y) 1 2let x1 = (function x -> function y -> x + y) 1 2let x2 = (function (x, y) -> x + y) (1, 2) 我们可优先考虑fun,因为它更为紧凑,在F#类库中你能看到很多这样的例子。 注意:本文中的代码均在F# 1.9.4.17版本下编写,在F# CTP 1.9.6.0版本下可能不能通过编译。 F#系列随笔索引页面