基础使用

fabric的典型使用方式就是,创建一个Python文件,该文件包含一到多个函数,然后使用fab命令调用这些函数。这些函数在fabric中成为task,下面是一个例子。

from fabric.api import *env.hosts = ['10.0.1.15', '10.0.1.16', '10.0.1.17']
env.port = 22
env.user = 'root'
env.password = '123456'def get_host_name():run('hostname')def get_local_file(path='.'):run('ls %s' % (path))def get_tail(path='/etc/passwd', linne=10):run('tail -n %s %s' % (linne, path))def hello():with settings(hide('everything'), warn_only=True):result = run('netstat -lntup|grep -w 25')print(result)print(result.return_code)print(result.failed)

命令行执行结果

获取列表

(play-test) D:\Users\CMSZ\Desktop\2020-Python\play-test\fabric>fab -f f1.py --list
Available commands:get_host_nameget_local_fileget_tailhello

获取列表

执行函数

--

(play-test) D:\Users\CMSZ\Desktop\2020-Python\play-test\fabric>fab -f f1.py --list
Available commands:get_host_nameget_local_fileget_tailhello(play-test) D:\Users\CMSZ\Desktop\2020-Python\play-test\fabric>fab -f f1.py get_host_name
[10.0.1.15] Executing task 'get_host_name'
[10.0.1.15] run: hostname
[10.0.1.15] out: cs7-1
[10.0.1.15] out:[10.0.1.16] Executing task 'get_host_name'
[10.0.1.16] run: hostname
[10.0.1.16] out: cs7-2
[10.0.1.16] out:[10.0.1.17] Executing task 'get_host_name'
[10.0.1.17] run: hostname
[10.0.1.17] out: cs7-3
[10.0.1.17] out:Done.
Disconnecting from 10.0.1.15... done.
Disconnecting from 10.0.1.16... done.
Disconnecting from 10.0.1.17... done.

fab -f f1.py get_host_name

-

(play-test) D:\Users\CMSZ\Desktop\2020-Python\play-test\fabric>fab -f f1.py hello
[10.0.1.15] Executing task 'hello'
/bin/bash: netstat: command not found
1
True
[10.0.1.16] Executing task 'hello'
/bin/bash: netstat: command not found
1
True
[10.0.1.17] Executing task 'hello'
/bin/bash: netstat: command not found
1
TrueDone.
Disconnecting from 10.0.1.15... done.
Disconnecting from 10.0.1.16... done.
Disconnecting from 10.0.1.17... done.

fab -f f1.py hello

(play-test) D:\Users\CMSZ\Desktop\2020-Python\play-test\fabric>fab -f f1.py get_local_file:/
[10.0.1.15] Executing task 'get_local_file'
[10.0.1.15] run: ls /
[10.0.1.15] out: bin   dev  home  lib64 mnt  proc  run   srv       sys  usr      var
[10.0.1.15] out: boot  etc  lib  media  opt  root  sbin  swapfile  tmp  vagrant
[10.0.1.15] out:[10.0.1.16] Executing task 'get_local_file'
[10.0.1.16] run: ls /
[10.0.1.16] out: bin   dev  home  lib64 mnt  proc  run   srv       sys  usr      var
[10.0.1.16] out: boot  etc  lib  media  opt  root  sbin  swapfile  tmp  vagrant
[10.0.1.16] out:[10.0.1.17] Executing task 'get_local_file'
[10.0.1.17] run: ls /
[10.0.1.17] out: bin   dev  home  lib64 mnt  proc  run   srv       sys  usr      var
[10.0.1.17] out: boot  etc  lib  media  opt  root  sbin  swapfile  tmp  vagrant
[10.0.1.17] out:Done.
Disconnecting from 10.0.1.15... done.
Disconnecting from 10.0.1.16... done.
Disconnecting from 10.0.1.17... done.

多个参数情况

需要注意的是:

  • 一次可以多个task,按照顺序执行: fab -f f1.py get_host_name get_local_file
  • 给task传递参数使用task:参数,多个参数按照位置进行传递(和Python相同,对于关键字的参数可以,在命令行中指定:fab get_local_file:path=/home)

fabric的命令行参数

fab命令作为fabric程序的入口提供了,丰富的参数调用.

-l:查看task列表
-f:指定fab的入口文件,默认是fabfile.py
-g:指定网管设备,比如堡垒机环境下,填写堡垒机的IP
-H:在命令行指定目标服务器,用逗号分隔多个服务器
-P:以并行方式运行任务,默认为串行
-R:以角色区分不同的服务
-t:连接超时的时间,以秒为单位
-w:命令执行失败时的警告,默认是终止任务
-- Fabric参数,其他包含fabric脚本的中的参数的快捷操作,比如--user,--port,或者直接跟要执行的Linux命令

如下例子,不写一行代码获取所有主机的ip地址

(play-test) D:\Users\CMSZ\Desktop\2020-Python\play-test>fab -H 10.0.1.16 --port 22 --user=root --password=123456 -- ip a
[10.0.1.16] Executing task '<remainder>'
[10.0.1.16] run: ip a
[10.0.1.16] out: 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
[10.0.1.16] out:     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[10.0.1.16] out:     inet 127.0.0.1/8 scope host lo
[10.0.1.16] out:        valid_lft forever preferred_lft forever
[10.0.1.16] out:     inet6 ::1/128 scope host
[10.0.1.16] out:        valid_lft forever preferred_lft forever
[10.0.1.16] out: 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
[10.0.1.16] out:     link/ether 52:54:00:75:dc:3d brd ff:ff:ff:ff:ff:ff
[10.0.1.16] out:     inet 10.0.2.15/24 brd 10.0.2.255 scope global noprefixroute dynamic eth0
[10.0.1.16] out:        valid_lft 76820sec preferred_lft 76820sec
[10.0.1.16] out:     inet6 fe80::5054:ff:fe75:dc3d/64 scope link
[10.0.1.16] out:        valid_lft forever preferred_lft forever
[10.0.1.16] out: 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
[10.0.1.16] out:     link/ether 08:00:27:3e:37:98 brd ff:ff:ff:ff:ff:ff
[10.0.1.16] out:     inet 10.0.1.16/24 brd 10.0.1.255 scope global noprefixroute eth1
[10.0.1.16] out:        valid_lft forever preferred_lft forever
[10.0.1.16] out:     inet6 fe80::a00:27ff:fe3e:3798/64 scope link
[10.0.1.16] out:        valid_lft forever preferred_lft forever
[10.0.1.16] out:

常用的对象和方法介绍 

介绍fabric中的env对象,以及其他的比如执行命令模块,上传文件等。

fabric中的env

 env是一个全局唯一的字典,保存了Fabric所有的配置,在Fabric的实现中,他是一个_AttributeDict()对象,之所以封装成_AttributeDict()对象,是覆盖了__getattr__和__setattr__,使我们可以使用“对象.属性=值”的方式,操作字典。

 我们可以通过源码的方式,查看env的配置参数,或者使用如下方式查看:

import json
from fabric.api import envprint(type(env))
print(json.dumps(env,indent=4))

<class 'fabric.utils._AttributeDict'>
{"abort_exception": null,"again_prompt": "Sorry, try again.","all_hosts": [],"combine_stderr": true,"colorize_errors": false,"command": null,"command_prefixes": [],"cwd": "","dedupe_hosts": true,"default_port": "22","eagerly_disconnect": false,"echo_stdin": true,"effective_roles": [],"exclude_hosts": [],"gateway": null,"gss_auth": null,"gss_deleg": null,"gss_kex": null,"host": null,"host_string": null,"lcwd": "","local_user": "CMSZ","output_prefix": true,"passwords": {},"path": "","path_behavior": "append","port": "22","real_fabfile": null,"remote_interrupt": null,"roles": [],"roledefs": {},"shell_env": {},"skip_bad_hosts": false,"skip_unknown_tasks": false,"ssh_config_path": "C:\\Users\\CMSZ\\.ssh\\config","sudo_passwords": {},"ok_ret_codes": [0],"sudo_prefix": "sudo -S -p '%(sudo_prompt)s' ","sudo_prompt": "sudo password:","sudo_user": null,"tasks": [],"prompts": {},"use_exceptions_for": {"network": false},"use_shell": true,"use_ssh_config": false,"user": "CMSZ","version": "1.14.post1","no_agent": false,"forward_agent": false,"abort_on_prompts": false,"rcfile": "C:\\Users\\CMSZ/.fabricrc","disable_known_hosts": false,"fabfile": "fabfile","hide": ["NO","DEFAULT"],"hosts": [],"key_filename": null,"no_keys": false,"keepalive": 0,"linewise": false,"connection_attempts": 1,"always_use_pty": true,"password": null,"parallel": false,"reject_unknown_hosts": false,"sudo_password": null,"system_known_hosts": null,"shell": "/bin/bash -l -c","show": ["NO","DEFAULT"],"timeout": 10,"command_timeout": null,"warn_only": false,"pool_size": 0
}Process finished with exit code 0

输出结果

常用的env配置如下:

  • env.hosts:定义目标服务器列表
  • env.exclude_hosts:排除特定的服务器
  • env.user SSH:到远程服务器的用户名
  • env.port:远程服务器的端口号
  • env.key_filename:私钥文件的位置
  • env.password SSH:到远程服务器的密码

针对不同主机不同密码的情况,可以使用如下的方式:

env.hosts = ['root@192.168.10.201:22','root@192.168.10.202:22','root@192.168.10.203:22'
]
env.passwords = {'root@192.168.10.201:22':'123456201','root@192.168.10.202:22':'123456202','root@192.168.10.203:22':'123456203'
}

fabric提供的命令

run():在远程服务器上执行Linux命令,还有一个重要的参数pty,如果我们执行命令以后需要有一个常驻的服务进程,那么就需要设置pty=False,避免因为Fabric退出导致进程的退出

run('service mysqld start',pty=False)

 PS:执行完毕会返回输出的信息,我们可以定义变量接受,同时这个返回信息有一个方法return_code,当返回的是正确执行的结果时code为0,否则不为0

def hello():with settings(hide('everything'),warn_only=True):   # 关闭显示result = run('anetstat -lntup|grep -w 25')print(result)                                   # 命令执行的结果print(result.return_code)                       # 返回码,0表示正确执行,1表示错误

输出

(play-test) D:\Users\CMSZ\Desktop\2020-Python\play-test\fabric>fab -f f1.py hello
[10.0.1.15] Executing task 'hello'
/bin/bash: netstat: command not found
1
True

sudo():与run类似,使用管理员权限在远程服务器上执行shell命令,还有一个重要的参数pty,如果我们执行命令以后需要有一个常驻的服务进程,那么就需要设置pty=False,避免因为Fabric退出导致进程的退出。

local():用以执行本地命令,返回要执行的命令,local是对Python的Subprocess模块的封装,更负载的功能可以直接使用Subprocess模块,包含capture参数,默认为False,表示subprocess输出的信息进行显示,如果不想显示,那么指定capture=True即可

def test():result = local('make test',capture=True)print(result)print(result.failed)print(result.succeeded)# 返回执行的命令
# 如果执行失败那么 result.failed 为True
# 如果执行成功那么 result.succeeded 为True

get():从远程服务器上获取文件,通过remote_path参数声明从何处下载,通过local_path表示下载到何处。remote_path支持通配符。

get(remote_path='/etc/passwd',local_path='/tmp/passwd')

put():将本地的文件上传到远程服务器,参数与get相似,此外,还可以通过mode参数执行远程文件的权限配置。

get(remote_path='/etc/passwd',local_path='/tmp/passwd')

reboot():重启远程服务器,可以通过wait参数设置等待几秒钟重启

reboot(wait=30)

propmt():用以在Fabric执行任务的过程中与管理员进行交互,类似于python的input

key = prompt('Please specify process nice level:',key='nice',validate=int)
# 会返回采集到的key

fabric的上下文管理器

env中存储的是全局配置,有时候我们并不希望修改全局配置参数,只希望临时修改部分配置,例如:修改当前工作目录,修改日志输出级别等。

在fabric中我们可以通过上下文管理器临时修改参数配置,而不会影响全局配置。当程序进入上下文管理器的作用域时,临时修改就会起作用;当程序离开上下文管理器时,临时修改就会消失。

cd():切换远程目录

def change(dir='/tmp'):with cd(dir):run('pwd')     # /tmprun('pwd')         # /root

lcd():切换本地目录

path():配置远程服务器PATH环境变量,只对当前会话有效,不会影响远程服务器的其他操作,path的修改支持多种模式

  • append:默认行为,将给定的路径添加到PATH后面。
  • prepend:将给定的路径添加到PATH的前面。
  • replace:替换当前环境的PATH变量。
def addpath():with path('/tmp','prepend'):run("echo $PATH")run("echo $PATH")

prefix():前缀,它接受一个命令作为参数,表示在其内部执行的代码块,都要先执行prefix的命令参数。

def testprefix():with cd('/tmp'):with prefix('echo 123'):run('echo 456')run('echo 789')# 转换为Linux命令为:
cd /tmp && echo '123' && echo '456'
cd /tmp && echo '123' && echo '789'

shell_env():设置shell脚本的环境变量 

def setenv():with shell_env(HTTP_PROXY='1.1.1.1'):run('echo $HTTP_PROXY')run('echo $HTTP_PROXY')# 等同于shell中的export
export HTTP_PROXY='1.1.1.1'

settings():通用配置,用于临时覆盖env变量

def who():with settings(user='dev'):    # 临时修改用户名为devrun('who')run('who')

remote_tunnel():通过SSH的端口转发建立的链接

with remote_tunnel(3306):run('mysql -uroot -p password')

hide():用于隐藏指定类型的输出信息,hide定义的可选类型有7种

  • status:状态信息,如服务器断开链接,用户使用ctrl+C等,如果Fabric顺利执行,不会有状态信息
  • aborts:终止信息,一般将fabric当作库使用的时候需要关闭
  • warnings:警告信息,如grep的字符串不在文件中
  • running:fabric运行过程中的数据
  • stdout:执行shell命令的标准输出
  • stderr:执行shell命令的错误输出
  • user:用户输出,类似于Python中的print函数

为了方便使用,fabric对以上其中类型做了进一步的封装

  • output:包含stdout,stderr
  • everything:包含stdout,stderr,warnings,running,user
  • commands:包含stdout,running

show():与hide相反,表示显示指定类型的输出

def hello():with settings(show('everything'), warn_only=True):result = run('ss -lntup|grep')print('1=' + result)print('2=' + str(result.return_code))print('3=' + str(result.failed))

(play-test) D:\Users\CMSZ\Desktop\2020-Python\play-test\fabric>fab -f f2.py hello
[10.0.1.15] Executing task 'hello'
[10.0.1.15] run: ss -lntup|grep
[10.0.1.15] out: Usage: grep [OPTION]... PATTERN [FILE]...
[10.0.1.15] out: Try 'grep --help' for more information.
[10.0.1.15] out:Warning: run() received nonzero return code 2 while executing 'ss -lntup|grep'!NoneType: None1=Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
2=2
3=True

结果

quiet():隐藏全部输出,仅在执行错误的时候发出告警信息,功能等同于 with settings(hide('everything'),warn_only=True) .

# 比如创建目录的时候,如果目录存在,默认情况下Fabric会报错退出,我们是允许这种错误的,所以针对这种错误,我们进行如下设置,使fabric只打出告警信息而不会中断执行。
with settings(warn_only=True)

装饰器

Fabric提供的命令一般都是执行某一个具体的操作,提供的上下文管理器一般都是用于临时修改配置参数,而fabric提供的装饰器,既不是执行具体的操作,也不是修改参数,而是控制如何执行这些操作,在那些服务器上执行这些操作,fabric的装饰器与人物执行紧密相关。下面从几个方面来进行说明

  • hosts:定制执行task的服务器列表
  • roles:定义执行task的role列表
  • parallel:并行执行task
  • serial:串行执行task
  • task:定义一个task
  • runs_once:该task只执行一次

fabric的task

task就是fabric需要在远程服务器上执行的函数,在fabric中有3中方法定义一个task

  1. 默认情况下,fabfile中每一个函数都是一个task。
  2. 继承自fabric的task类,这种方式比较难用,不推荐。
  3. 使用fabric的task装饰器,这是使用fabric最快速的方式,也是推荐的用法。
from fabric.api import *env.user='root'
env.password='mysql123'@task
def hello():run('echo hello')def world():run('echo world')

PS:默认情况下,fabfile中的所有函数对象都是一个task,但是如果我们使用了task装饰器,显示的定义了一个task,那么,其他没有通过task装饰器装饰的函数将不会被认为是一个task。

fabric的host

为了方便我们的使用,fabric提供了非常灵活的方式指定对哪些远程服务器执行操作,根据我们前面的知识,我们知道有两种方式:通过env.hosts来执行,或者在fab执行命令的时候使用-H参数,除此之外,还有以下需要注意的地方

  1. 指定host时,可以同时指定用户名和端口号: username@hostname:port
  2. 通过命令行指定要多哪些hosts执行人物:fab mytask:hosts="host1;host2"
  3. 通过hosts装饰器指定要对哪些hosts执行当前task
  4. 通过env.reject_unkown_hosts控制未知host的行为,默认True,类似于SSH的StrictHostKeyChecking的选项设置为no,不进行公钥确认。
from fabric.api import *env.hosts = ['root@192.168.10.201:22','root@192.168.10.202:22','root@192.168.10.203:22'
]
env.passwords = {'root@192.168.10.201:22':'123456201','root@192.168.10.202:22':'123456202','root@192.168.10.203:22':'123456203'
}@hosts('root@192.168.10.201:22')
@task
def hello():run('ifconfig br0')# 命令行的方式:
fab hello:hosts="root@192.168.10.201;root@192.168.10.202"

fabric的role

role是对服务器进行分类的手段,通过role可以定义服务器的角色,以便对不同的服务器执行不同的操作,Role逻辑上将服务器进行了分类,分类以后,我们可以对某一类服务器指定一个role名即可。进行task任务时,对role进行控制。

# role在env.roledefs中进行定义
env.roledefs = {'web':['root@192.168.10.201','192.168.10.202']    # role名称为:web'db':['root@192.168.10.203',]                     # role名称为:db
}当我们定义好role以后,我们就可以通过roles装饰器来指定在哪些role上运行task。

from fabric.api import *env.roledefs = {'web':['root@192.168.10.201:22','root@192.168.10.202:22',],'db':['root@192.168.10.203:22',]
}
env.passwords = {'root@192.168.10.201:22':'123456201','root@192.168.10.202:22':'123456202','root@192.168.10.203:22':'123456203'
}@roles('db')       # 只对role为db的主机进行操作
@task
def hello():run('ifconfig br0')

 注意:hosts装饰器可以和roles装饰器一起使用(全集),看起来容易造成混乱,不建议混搭。

fabric的执行模型

fabric执行任务的步骤如下:

  1. 创建任务列表,这些任务就是fab命令行参数指定的任务,fab会保持这些任务的顺序
  2. 对于每个任务,构造需要执行该任务的服务器列表,服务器列表可以通过命令行参数指定,或者env.hosts指定,或者通过hosts和roles装饰器指定
  3. 遍历任务列表,对于每一台服务器分别执行任务,可以将任务列表和服务器列表看作是两个for循环,任务列表是外层循环,服务器列表是内存循环,fabric默认是串行执行的可以通过装饰器或者命令行参数确定任务执行的方式
  4. 对于没有指定服务器的任务默认为本地任务,仅执行一次

PS:关于并行模式:

  1. 通过命令行参数-P(--parallel)通知Fabric并行执行task
  2. 通过env.parallel设置设否需要并行执行
  3. 通过parallel装饰器通知Fabric并行执行task,它接受一个pool_size作为参数(默认为0),表示可以有几个任务并行执行

其他装饰器

前面介绍了task,hosts,roles和parallel装饰器,此外还有两个装饰器比较常用

  • runs_once:只执行一次,防止task被多次调用。例如,对目录打包进行上传,上传动作对不同的服务器可能会执行多次,但是打包的动作只需要执行一次即可。
  • serial:强制当前task穿行执行。使用该参数时优先级最高,即便是制定了并发执行的参数

常用的功能函数

fabric中还有其他的一些好用的函数

封装task

fabric提供了一个execute函数,用来对task进行封装。它最大的好处就是可以将一个大的任务拆解为很多小任务,每个小任务互相独立,互不干扰

from fabric.api import *env.roledefs = {'web':['root@192.168.10.201:22','root@192.168.10.202:22',],'db':['root@192.168.10.203:22',]
}
env.passwords = {'root@192.168.10.201:22':'123456201','root@192.168.10.202:22':'123456202','root@192.168.10.203:22':'123456203'
}@roles('db')
def hello():run('echo hello')@roles('web')
def world():run('echo world')@task
def helloworld():execute(hello)execute(world)

 # 函数helloworld作为入口,分别调用两个task,对不同的主机进行操作

utils函数

包含一些辅助行的功能函数,这些函数位于fabric.utils下,常用的函数如下:

  1. abort:终止函数执行,打印错误信息到stderr,并且以退出码1退出。
  2. warn:输出警告信息,但是不会终止函数的执行
  3. puts:打印输出,类似于Python中的print函数
def helloworld():execute(hello)abort('----->abort')     # 执行到这里时,直接退出warn('----->warn')       # 会发出提示信息,不会退出puts('----->puts')       # 会打印括号中的信息execute(world)

带颜色的输出 

 fabric为了让输出日志更具有可读性,对命令行中断的颜色输出进行了封装,使用print打印带有不同颜色的文本,这些颜色包含在fabric.colors中。像warn,puts打印输出的,也可以直接渲染颜色

  • blue(text,blod=False)  蓝色
  • cyan(text,blod=False)  淡蓝色
  • green(text,blod=False)  绿色
  • magenta(text,blod=False)  紫色
  • red(text,blod=False)  红色
  • white(text,blod=False)  白色
  • yellow(text,blod=False)   黄色
def ls(path='.'):run('ls {0}'.format(path))def hello():execute(hell)  # task任务hellwarn(yellow('----->warn'))  # 会发出提示信息,不会退出puts(green('----->puts'))  # 会打印括号中的信息execute(ls) # task任务lsprint(green('the text is green')) # 单纯的渲染文字:def hell(name='world'):print('hello %s' % name)

确认信息

有时候我们在某一步执行错误,会给用户提示,是否继续执行时,confirm就非常有用了,它包含在 fabric.contrib.console中

def testconfirm():result = confirm('Continue Anyway?')print(result)# 会提示输入y/n
# y 时 result为True
# n 时 result为False

使用Fabric源码安装redis

下载一个redis的包和fabfile.py放在同级目录即可,不同目录需要修改包的位置,这里使用的是redis-4.0.9版本。

#!/usr/bin/env python3
from fabric.api import *
from fabric.contrib.console import confirm
from fabric.utils import abort
from fabric.colors import *env.hosts = ['192.168.10.202',]
env.user = 'root'
env.password = '123456202'@runs_once
@task
def test():with settings(warn_only=True):local('tar xf redis-4.0.9.tar.gz')with lcd('redis-4.0.9'):result = local('make test',capture=True)if result.failed and not confirm('Test is Faild Continue Anyway?'):abort('Aborting at user request.')with lcd('redis-4.0.9'):local("make clean")local('tar zcvf redis-4.0.10.tar.gz redis-4.0.9')@task
def deploy():put('redis-4.0.10.tar.gz','/tmp/')with cd('/tmp'):run('tar xf redis-4.0.10.tar.gz')with cd('redis-4.0.9'):sudo('make install')@task
def start_redis():with settings(warn_only=True):result = run('netstat -lntup | grep -w redis-server')if result.return_code == 0:print(green('redis is started!'))else:run('set -m ; /usr/local/bin/redis-server &')   # 用pty=False, fabric进程退不出来,不知道为啥,所以这里用set -mprint(green('redis start Successful'))@task
def clean_local_file():local('rm -rf redis-4.0.10.tar.gz')@task
def clean_file():with cd('/tmp'):sudo('rm -rf redis-4.0.9')sudo('rm -rf redis-4.0.10.tar.gz')@task
def install():execute(test)execute(deploy)execute(clean_file)execute(clean_local_file)<br><code class="python spaces hljs">     </code><code class="python plain hljs">execute(start_redis)</code>1
2
3
PS:关于set -m 的作用如下:"set -m" turns on job control, you can run processes in a separate process group.<br>理解:在一个独立的进程组里面运行我们的进程。

参考链接

https://www.cnblogs.com/xiao-apple36/p/9124292.html#_label6_5

Fabric 代码发布相关推荐

  1. 测试代码发布到博客效果(Windows Live Writer发布)

    测试代码发布到博客效果(Windows Live Writer发布) public class SwitchCase {/*** 1.switch后面的表达式为常量表达式,类型只能是可以转化为int. ...

  2. QuickTime 0day ***代码发布,可能允许执行任意代码

    QuickTime 0day ***代码发布,可能允许执行任意代码 仅仅在 Apple 升级播放器堵上九个严重安全漏洞之后的一个星期,一个暂无补丁的 Apple QuickTime 缺陷就于星期二被发 ...

  3. ansible代码发布系统

    ansible - 代码发布系统 ssh 秘钥登录 ssh-keygen # 用来生成ssh的密钥对 ssh-copy-id 192.168.107.131 # 复制秘钥到远程主机 ansible 命 ...

  4. jenkins配置记录(2)--代码发布流程

    在我们的日常运维工作中,使用jenkins来完成业务代码发版上线是至关重要的一环. 前面已经提到在jenkins上添加用户权限的操作,今天重点说下如何在jenkins下构建项目工程进行代码发布? 在此 ...

  5. 【nexus】nexus 仓库组的概念 以及相关配置 代码发布相关

    文章目录 1.概述 2.仓库分类 3.仓库配置 4.代码发布 1.概述 视频地址:视频 一般情况下,我们构建了一个私服,然后我们可以对我们的私服上传下载东东,但是我们的中央仓库,是不能这样的.. 这样 ...

  6. docker.11-基于Docker容器DevOps应用方案 企业业务代码发布系统

    基于Docker容器DevOps应用方案 企业业务代码发布系统 一.企业业务代码发布方式 1.1 传统方式 以物理机或虚拟机为颗粒度部署 部署环境比较复杂,需要有先进的自动化运维手段 出现问题后重新部 ...

  7. 企业的代码发布解决方案

    企业的代码发布解决方案 小型公司(3-20台服务器) 使用FTP之间上传代码到服务器(使用 rz 的方式) 多使用PHP语言进行开发 缺乏测试人员,对网站用户的体验比较差 小公司上线的建议:(上线:提 ...

  8. python怎么做网页制作_[源代码]Python爬取网页制作电子书代码发布

    最近,在GitChat发布一场Chat(Chat地址请猛戳这里),人数当天就达标了,今天把文章完成提交,同时将文章中的代码发布到码云,我就等待大家前来捧场了,Chat地址请猛戳这里. 有人爬取数据分析 ...

  9. 看地图人,如何零代码发布莆田系医院在线地图

    最近"魏则西"事件引起民愤,作为一个gis人,除了愤怒以外,我们该做些什么来表达我们的愤怒?最近看了好几篇新闻报道,包括凤凰网.网易等,都曝光了莆田系医院的名单,作为gis,我自然 ...

最新文章

  1. git merge 冲突_更新了!深入浅出图解Git,入门到精通(保姆级教程)第三篇
  2. java build.gradle 详解_java – Gradle构建失败[无法解析配置的所有依赖项’:compile’.]...
  3. java——maven依赖版本冲突
  4. wsus问题之无法访问 WSUS 控制台
  5. Spark3.1.1 Docker镜像中修改/etc/hosts
  6. vim编辑器的使用--转自MJ学长
  7. matlab的精度变量,MatLab - 变量精度算术
  8. 在小范围内[打表]验证哥德巴赫猜想(洛谷P1579题题解,Java语言描述)
  9. 利用colab训练YOLOv5
  10. python不带颜色的图形_python-Matplotlib添加基于现有颜色系列的图例
  11. 01-04 Linux常用命令-网络相关
  12. 冷热分离和直接使用大数据库_「系统架构」如何通过分离冷热数据提升系统性能?...
  13. 最少拦截系统 贪心
  14. 试题7 算法训练 P0505(最右边的那个非0的数字)
  15. 第六节课-(第七节课)训练神经网络-2
  16. 计算机鼠标双击怎么,电脑鼠标双击变成属性怎么办-解决电脑鼠标双击变成属性的方法 - 河东软件园...
  17. 游戏角色命名与游戏风格
  18. 合并报表编制采用的理论_合并报表的基本逻辑是什么?
  19. 算法第3章上机实践报告
  20. Wireshark抓包实例诊断TCP连接问题

热门文章

  1. linux ping策略打开_linux ping策略打开_如何在Linux服务器禁止和开启ping包 互联网技术圈 互联网技术圈......
  2. html 属于mvvm框架,mvvm模式和mvc的区别是什么?
  3. 返回值类型与函数类型不匹配_golang基础语法,定义函数类型 为已存在的数据类型起别名...
  4. linux 重启_四步见证linux系统重启过程,小心操作,防止后悔!
  5. 并联串联混合的电压和电流_电流互感器一次绕组串联、并联,二次绕组串联、并联的相关问题...
  6. mysql不需要安装_MySQL免安装版 配置
  7. Batch Norm常用方法
  8. 解决ubuntu中vi不能正常使用方向键与退格键的问题
  9. 不吹不黑,中美程序员的区别对比!
  10. 技高一筹!Python奶爸的鸡娃日常!