Fabric: ํŒจ๋ธŒ๋ฆญ์€ Invoke์™€ ๊ฐ™์ด ํ™˜๊ฒฝ์„ ๋กœ์ปฌ ์…ธ๋กœ ์ „๋‹ฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2018๋…„ 05์›” 11์ผ  ยท  14์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: fabric/fabric

fabfile.py ๋ฐ tasks.py ๋กœ ์ €์žฅ๋œ์ด ์ž‘์—… ์ •์˜๋ฅผ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค.

from invoke import task

<strong i="8">@task</strong>
def make(c):
    c.run('env')

fab make ์ถœ๋ ฅ :

PWD=/tmp
SHLVL=1
_=/usr/bin/env

inv make ์ถœ๋ ฅ :

LC_ALL=en_US.UTF-8
NVM_DIR=/home/justinas/.nvm
LC_MEASUREMENT=en_US.UTF-8
LC_PAPER=en_US.UTF-8
LC_MONETARY=en_US.UTF-8
<...> (lots of stuff in my environment)

์ฒ˜์Œ์—๋Š” PATH ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•˜์—ฌ ์ž‘๋™ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์‹คํ–‰ ํŒŒ์ผ์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” fpm ์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์ด๊ฒƒ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.

from invoke import task

<strong i="22">@task</strong>
def make(c):
    c.run('fpm -s dir -t rpm -C dist --name somename .')

์ด๊ฒƒ์€ invoke์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜์ง€๋งŒ fab์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

justinas<strong i="26">@js</strong>:/tmp$ fab make
{:timestamp=>"2018-05-11T13:11:26.218874+0300", :message=>"Need executable 'rpmbuild' to convert dir to rpm", :level=>:error}
justinas<strong i="27">@js</strong>:/tmp$ inv make
{:timestamp=>"2018-05-11T13:11:29.967762+0300", :message=>"Created package", :path=>"somename-1.0-1.x86_64.rpm"}
Bug Connection Needs investigation run()

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋‚˜๋Š” ์ด๊ฒƒ๋„ ๋งŒ๋‚ฌ๋‹ค. ๋‚˜๋Š” c.run('make build') ํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ๋‚ด ENV๊ฐ€ ํ’€๋ฆฌ์ง€ ์•Š์•˜๋‹ค (ํŠนํžˆ ๋นŒ๋“œ ์‹คํŒจ๋ฅผ ์ผ์œผํ‚จ GOPATH). replace_env=False ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ํŽธ์ง‘ : ๋‚˜๋Š” ๋ฌธ์„œ ์— ๋”ฐ๋ผ ๋ณธ๋‹ค :

run.replace_env : False ๋Œ€์‹  True์ด๋ฏ€๋กœ ์›๊ฒฉ ๋ช…๋ น์ด ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค์˜ ๋ณต์‚ฌ๋ณธ์„ ์ƒ์†ํ•˜๋Š” ๋Œ€์‹  '๊นจ๋—ํ•œ'๋นˆ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๋กœ์ปฌ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ ค๊ณ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์•ฝ๊ฐ„ ํ˜ผ๋ž€ ์Šค๋Ÿฌ์› ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  14 ๋Œ“๊ธ€

์ด ํ–‰๋™์— ๋Œ€ํ•œ ์„ค๋ช… ์„ ๋ฐœ๊ฒฌ

์ด๊ฒƒ์€ ์›๊ฒฉ ์‹œ์Šคํ…œ์—์„œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค.

$ env | wc -l
      41
$ ssh testdeploy01.ec2.st-av.net env | wc -l
      14
$ ssh testdeploy01.ec2.st-av.net grep Env /etc/ssh/sshd_config
AcceptEnv LANG LC_*
         Specifies what environment variables sent by the client will be copied into
         the session's environ(7).  See SendEnv in ssh_config(5) for how to configure
         the client.  The TERM environment variable is always sent whenever the
         client requests a pseudo-terminal as it is required by the protocol.  Vari-
         ables are specified by name, which may contain the wildcard characters `*'
         and `?'.  Multiple environment variables may be separated by whitespace or
         spread across multiple AcceptEnv directives.  Be warned that some environ-
         ment variables could be used to bypass restricted user environments.  For
         this reason, care should be taken in the use of this directive.  The default
         is not to accept any environment variables.

์ „์ฒด ๋กœ์ปฌ ํ™˜๊ฒฝ์„ ์ˆ˜์ง‘ํ•˜๊ณ  ๋‹ค๋ฅธ์ชฝ์— ์„ค์ •ํ•˜์—ฌ ๋ชจ๋“  ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ํ†ต๊ณผํ•˜๋ ค๊ณ  ์‹œ๋„ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ PATH ์™€ ๊ฐ™์€ ์›๊ฒฉ ์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ์ ์ ˆํ•œ ๊ฐ’๊ณผ ์ถฉ๋Œ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฌด์‹œํ•ด์•ผํ•˜๋Š” ๋งŽ์€ ๋ณ€์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. GOPATH (Go ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ), TMPDIR , HOME , SSH_AUTH_SOCK , ...

๋‚˜๋Š” ์ „์ ์œผ๋กœ ๋กœ์ปฌ ์ž‘์—…์— ๋Œ€ํ•ด์„œ๋งŒ ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋กœ์ปฌ ๋ช…๋ น์— ๋Œ€ํ•ด ์ „๋‹ฌ ํ™˜๊ฒฝ์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ์ผœ์ ธ ์žˆ์–ด์•ผ ํ•จ์„ ํ™•์ธ ํ•˜๋Š” TODO ์ฃผ์„ ๋„ ๋ฐœ๊ฒฌ

์•„, ์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค.

@justinas ๋กœ์ปฌ ์ž‘์—…์— ๋Œ€ํ•ด ํ˜ธ์ถœ์—์„œ ์‹คํ–‰์„ ์‚ฌ์šฉํ•˜์—ฌ ๋๋‚ฌ

from invoke import run as local

<strong i="7">@task</strong>
def test(c):
    local('ls')

์ด๊ฒƒ์€ # 1752์˜ ํŒจ์‹ฏ์ž…๋‹ˆ๋‹ค-์˜๋„๋Š” local ๊ฐ€ Invoke์ฒ˜๋Ÿผ ์ž‘๋™ํ•˜๊ณ  env๋ฅผ ๋ณด์กดํ•˜๊ณ  run ๊ฐ€ SSH์ฒ˜๋Ÿผ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๊ณ  env๋ฅผ ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ง€๊ธˆ์€์ด ๋™์ž‘์„ ์œ ๋„ํ•˜๋Š” ๊ตฌ์„ฑ์ด ์ œ๋Œ€๋กœ ๋ถ„๋ฆฌ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์‚ฌ์‹ค์ƒ ๋ฒ„๊ทธ์ž…๋‹ˆ๋‹ค. ๊ณง ์ˆ˜์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์‘๋‹ต ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

๋‚˜๋Š” ๋ฐฉ๊ธˆ ๊ฐ™์€ ๋ฌธ์ œ์— ๋ถ€๋”ช ํ˜”๊ณ  ๋ฒ„๋ ค์ง€๋Š” ๊ฒƒ์€ ์ง€์—ญ ํ™˜๊ฒฝ ๋ฟ๋งŒ์ด ์•„๋‹ˆ๋ผ๋Š” ์ ์— ์ฃผ๋ชฉํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฒ„๊ทธ๋„ ์ด๋ฏธ ์•Œ๊ณ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ช…ํ™•ํžˆํ•˜๊ธฐ ์œ„ํ•ด ์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

<strong i="8">@task</strong>
def test(c):
    c.run('echo $ENV', env={'ENV': 'production'}) # no output

๋‹น๋ถ„๊ฐ„ ๋‚˜๋Š” ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š”์ด ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• (๋งค์šฐ ๊นจ๋—ํ•˜์ง€ ์•Š์Œ)์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค.

<strong i="12">@task</strong>
def test(c):
    with c.prefix('ENV=production'):
        c.run('echo $ENV') # prints "production"

์˜ˆ, ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

์ง€๊ธˆ์€ run('...', preserve_env=True) ๋ผ๊ณ  ๋งํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. IIRC.

preserve_env ์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. replace_env=False ์–ธ๊ธ‰ ํ•˜์…จ๋‚˜์š”?
๊ทธ๊ฒƒ์€ ์˜ค๋ฅ˜๋ฅผ ์œ ๋ฐœํ•˜์ง€ ์•Š์ง€๋งŒ ํ™˜๊ฒฝ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹ํ๊ธฐ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”์‹  : ๋กœ์ปฌ์ด ์•„๋‹Œ ์›๊ฒฉ ์ž‘์—…์„์œ„ํ•œ ํ™˜๊ฒฝ์„ ์„ค์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋„ค, replace_env ์„ (๋ฅผ) ์˜๋ฏธํ–ˆ๋Š”๋ฐ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ด์ƒํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ์„ฑ์„ ๋กœ์ปฌ / ์›๊ฒฉ (# 1752)์œผ๋กœ ๋ถ„ํ•  ํ•  ๋•Œ ์‚ดํŽด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด๊ฒƒ๋„ ๋งŒ๋‚ฌ๋‹ค. ๋‚˜๋Š” c.run('make build') ํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ๋‚ด ENV๊ฐ€ ํ’€๋ฆฌ์ง€ ์•Š์•˜๋‹ค (ํŠนํžˆ ๋นŒ๋“œ ์‹คํŒจ๋ฅผ ์ผ์œผํ‚จ GOPATH). replace_env=False ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ํŽธ์ง‘ : ๋‚˜๋Š” ๋ฌธ์„œ ์— ๋”ฐ๋ผ ๋ณธ๋‹ค :

run.replace_env : False ๋Œ€์‹  True์ด๋ฏ€๋กœ ์›๊ฒฉ ๋ช…๋ น์ด ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค์˜ ๋ณต์‚ฌ๋ณธ์„ ์ƒ์†ํ•˜๋Š” ๋Œ€์‹  '๊นจ๋—ํ•œ'๋นˆ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๋กœ์ปฌ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ ค๊ณ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์•ฝ๊ฐ„ ํ˜ผ๋ž€ ์Šค๋Ÿฌ์› ์Šต๋‹ˆ๋‹ค.

๋กœ์ปฌ ๋ช…๋ น์„ ์‹คํ–‰ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ์—ฌ์ „ํžˆ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ๋ฟก ๋นต๋€จ

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰