0% found this document useful (0 votes)
51 views52 pages

Shell Script Moderno - Aurelio Jargas

The document discusses the evolution of sysadmin work from the 1990s to modern times. In the 1990s, sysadmin tasks involved manually installing Linux distributions on physical servers, recompiling kernels, editing configuration files, and starting services. Today, sysadmin work utilizes virtual machines, cloud platforms, configuration management tools like Puppet and Chef, Docker containers, and continuous integration tools like Jenkins and Travis CI to deploy and manage infrastructure and applications with greater automation and ease. Shell scripts continue to play an important role in automating tasks and integrating various modern devops tools and platforms.

Uploaded by

vjnrv
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
51 views52 pages

Shell Script Moderno - Aurelio Jargas

The document discusses the evolution of sysadmin work from the 1990s to modern times. In the 1990s, sysadmin tasks involved manually installing Linux distributions on physical servers, recompiling kernels, editing configuration files, and starting services. Today, sysadmin work utilizes virtual machines, cloud platforms, configuration management tools like Puppet and Chef, Docker containers, and continuous integration tools like Jenkins and Travis CI to deploy and manage infrastructure and applications with greater automation and ease. Shell scripts continue to play an important role in automating tasks and integrating various modern devops tools and platforms.

Uploaded by

vjnrv
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 52

Shell Script

Moderno
Aurelio Jargas
http://aurelio.net
@oreio
Sysadmin anos 90
Sysadmin hoje

Foto: caminholivre.wordpress.com
Sysadmin dos anos 90

Servidor físico (empoeirado)

CD do Linux

Instala a distro

Recompila o kernel

Instala pacotes

Edita arquivos .conf

Inicia serviços

Feito!
Sysadmin dos anos 90

Servidor físico (empoeirado)

CD do Linux

Instala a distro

Recompila o kernel

Instala pacotes

Edita arquivos .conf

Inicia serviços

Feito!
} install.sh
VM

Cloud

Docker
Sysadmin / DevOps moderno

AWS / Azure / Google Cloud

Puppet / Chef / Ansible

GitHub / GitLab / Bitbucket

Jenkins

Travis CI / GitLab CI

Docker
Meu precioso servidor,
criado “na mão”
com muito ♥
Hoje eu lanço e destruo servidores.
Com um clique.
Sem pensar muito.
E o shell?
Ambientes de execução de scripts

Linha de comando

$ meu-script.sh foo

Cron

0 * * * * root /bin/meu-script.sh foo


Git
Git hooks

$ ls /path/to/my/repo/.git/hooks/
applypatch-msg.sample pre-push.sample
commit-msg.sample pre-rebase.sample
post-update.sample prepare-commit-msg.sample
pre-applypatch.sample update.sample
pre-commit.sample
$
Git hooks

$ cat app.bare.git/hooks/post-receive
#!/bin/bash -exu

echo "Executando post-receive em producao"


unset GIT_DIR
cd /opt/repo/foobar.git
git checkout producao
git pull
$
CI

Travis, GitLab
Travis CI

language: bash

before_install:
- url_base="https://raw.githubusercontent.com/aureliojargas"
- curl -sOL "${url_base}/clitest/master/clitest"
- chmod +x clitest
- mv clitest testador

script:
- cd testador
- ./run
Travis CI

language: bash

before_install:
- url_base="https://raw.githubusercontent.com/aureliojargas"
- curl -sOL "${url_base}/clitest/master/clitest"
- chmod +x clitest
- mv clitest testador

script:
- cd testador
- ./run
GitLab CI

code_lint:
script:
- date
- uname -a
- env
- ls -la
- cd wp-content/plugins/foo-setup
- phpcs .
- cd -
- cd wp-content/themes/foo
- phpcs --ignore=bootstrap,inc,js,css .
- cd -
unit_tests:
script:
- cd wp-content/plugins/foo-setup
- WP_TESTS_DIR=/opt/wp-tests/wp-tests-lib phpunit
GitLab CI

code_lint:
script:
- date
- uname -a
- env
- ls -la
- cd wp-content/plugins/foo-setup
- phpcs .
- cd -
- cd wp-content/themes/foo
- phpcs --ignore=bootstrap,inc,js,css .
- cd -
unit_tests:
script:
- cd wp-content/plugins/foo-setup
- WP_TESTS_DIR=/opt/wp-tests/wp-tests-lib phpunit
Puppet
Puppet

exec { '/bin/echo root >> /usr/lib/cron/cron.allow':


path => '/usr/bin:/usr/sbin:/bin',
unless => 'grep root /usr/lib/cron/cron.allow 2>/dev/null',
}

exec { 'tar -xf /Volumes/nfs02/important.tar':


cwd => '/var/tmp',
creates => '/var/tmp/myfile',
path => ['/usr/bin', '/usr/sbin',],
}
Jenkins
Jenkins
Docker
Docker

FROM debian:jessie

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y curl

COPY . /app
WORKDIR /app

ENV PATH /app:$PATH


ENV ZZPATH /app/funcoeszz
ENV ZZDIR /app/zz

ENTRYPOINT ["bash", "funcoeszz"]


CMD ["--help"]
Docker

FROM debian:jessie

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y curl

COPY . /app
WORKDIR /app

ENV PATH /app:$PATH


ENV ZZPATH /app/funcoeszz
ENV ZZDIR /app/zz

ENTRYPOINT ["bash", "funcoeszz"]


CMD ["--help"]
Docker

FROM debian:jessie

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y curl

COPY . /app
WORKDIR /app

ENV PATH /app:$PATH


ENV ZZPATH /app/funcoeszz
ENV ZZDIR /app/zz

ENTRYPOINT ["bash", "funcoeszz"]


CMD ["--help"]
Docker

FROM debian:jessie
cp -r . /app
ARG DEBIAN_FRONTEND=noninteractive
cd
RUN apt-get update/a&&
pp apt-get install -y curl

COPY . /app
WORKDIR /app

ENV PATH /app:$PATH


ENV ZZPATH /app/funcoeszz
ENV ZZDIR /app/zz

ENTRYPOINT ["bash", "funcoeszz"]


CMD ["--help"]
Docker

FROM debian:jessie

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y curl

COPY . /app
WORKDIR /app

ENV PATH /app:$PATH


ENV ZZPATH /app/funcoeszz
ENV ZZDIR /app/zz

ENTRYPOINT ["bash", "funcoeszz"]


CMD ["--help"]
Docker
export DEBIA
N_FRONTEND="
noninteractive"
FROM debian:jessie

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y curl

COPY . /app export PATH=


"/app:$PATH"
WORKDIR /app export ZZPAT
H="/app/func
export ZZDIR oeszz"
="/app/zz"
ENV PATH /app:$PATH
ENV ZZPATH /app/funcoeszz
ENV ZZDIR /app/zz

ENTRYPOINT ["bash", "funcoeszz"]


CMD ["--help"]
Docker

FROM debian:jessie

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y curl
if test $# -gt 0
COPY . /app then
WORKDIR /app bash funcoeszz "$@"
else
ENV PATH /app:$PATH bash funcoeszz --help
fi
ENV ZZPATH /app/funcoeszz
ENV ZZDIR /app/zz

ENTRYPOINT ["bash", "funcoeszz"]


CMD ["--help"]
Boas práticas
Explore o ambiente

$ date
$ uname -a
$ env | sort
$ whoami
$ groups
$ ls -la
$ ps auxw

$ git branch
$ git status

$ docker info
$ docker ps
Use funções para organizar o script

#!/bin/bash

build() {
docker build ...
}
publish() {
docker push ...
docker rmi ...
}
run() {
docker run ...
}

build
publish
run
Crie uma pasta “scripts” no repositório

$ ls -1 scripts/
_lib.sh
build.sh
cleanup.sh
database-reset.sh
deploy.sh
merge-branch.sh
publish.sh
test.sh
$
Pratique POSIX

#!/bin/sh

Evite arrays
Evite ${variavel/isso/aquilo}
Evite ${variavel:1:3}
Evite [[
Evite $FUNCNAME
Evite for(;;)
Evite $'…'
Evite comando < <(comando)
Seja --verbose, mande tudo para STDOUT

echo "Iniciando em $(date)"

echo "Copiando os arquivos para $destino"


cp -v * "$destino"

echo
echo "Iniciando o backup"
tar cvzf meuapp-$timestamp.tgz "$destino"

echo "Finalizando em $(date)"


Nomenclatura de variáveis

Maiúsculas para variáveis de ambiente:


$PATH
$BUILD_ID
$TRAVIS_OS_NAME

Minúsculas para variáveis do script:


base_dir=$(pwd)
base_url='http://example.com'
use_colors=1

Minúsculas para variáveis locais de funções:


local i=0
local branch
local path
Conheça as variáveis do seu ambiente

Jenkins GitLab CI Travis

$BUILD_ID $CI_BUILD_ID $TRAVIS_BUILD_NUMBER

$BUILD_NUMBER $CI_BUILD_NAME $TRAVIS_JOB_NUMBER

$BUILD_URL $CI_BUILD_STAGE $TRAVIS_COMMIT

$JOB_NAME $CI_SERVER_NAME $TRAVIS_OS_NAME

$GIT_COMMIT $CI_PROJECT_DIR $TRAVIS_PYTHON_VERSION


Use variáveis de ambiente

$ ./meu-script.sh meu-app master 123

$ REPO=meu-app BRANCH=master VERSION=132 ./meu-script.sh


Use o modo “strict” do bash

#!/bin/bash

# Modo strict
set -euo pipefail

# set -e para abortar o script se houver qualquer erro


cp /etc/passwd

# set -u para tornar erro acessar variável não existente


echo "$foo"

# set -o pipefail para ajustar o exit code de um pipeline


grep root /etc/passssswd | sort
Use o modo “strict” do bash (com exceções)

#!/bin/bash

# Modo strict
set -euo pipefail

# set -e para abortar o script se houver qualquer erro


cp /etc/passwd || true

# set -u para tornar erro acessar variável não existente


echo "${foo:-}"

# set -o pipefail para ajustar o exit code de um pipeline


grep root /etc/passssswd | sort
Ligue o debug com $DEBUG

#!/bin/bash

test -n "$DEBUG" && set -x

Para executar:
$ ./meu-script.sh # sem debug
$ DEBUG=1 ./meu-script.sh # com debug
Ligue o debug com $DEBUG - strict

#!/bin/bash

set -euo pipefail

test -n "${DEBUG:-}" && set -x


Ferramentas
shellcheck
http://www.shellcheck.net

$ shellcheck meu-script.sh

Line 3:
for f in $(ls *.txt)
^-- SC2045: Iterating over ls output is fragile.

Line 5:
grep -i nofx.*mp3 $f
^-- SC2062: Quote the grep pattern so the shell won't
interpret it.
^-- SC2086: Double quote to prevent globbing and
word splitting.
jq - Parser de JSON
https://stedolan.github.io/jq/

$ cat foo.json
{ "foo": { "bar": { "baz": 123 } } }
$ cat foo.json | jq .
{
"foo": {
"bar": {
"baz": 123
}
}
}
$ cat foo.json | jq .foo.bar.baz
123
$
curl, sed

$ curl --location -D headers.txt http://www.example.com

$ sed -i "s/%hostname%/$(hostname)/" /etc/app.conf

$ sed -i '/debug/ s/false/true/' /etc/app.conf

$ docker exec meu-app sed -i '/debug/ s/false/true/' /etc/app.conf


Cloud CLI

AWS aws
https://aws.amazon.com/cli/

Azure azure
https://github.com/Azure/azure-xplat-cli

DigitalOcean doctl
https://github.com/digitalocean/doctl

Google Cloud gcloud, gsutil, bq, kubectl


https://cloud.google.com/sdk/

IBM Bluemix e Cloud Foundry bluemix, cf


https://clis.ng.bluemix.net

Rackspace rack
https://developer.rackspace.com/docs/rack-cli/
Perguntas?
@oreio
$ __

You might also like