adiciona pasta exemplos com exercicios Python, Docker e Linux comentados em portugues
- python/: 25 exercicios classicos de entrevistas SWE (sort, search, DP, estruturas de dados) - docker/: 9 cenarios de containerizacao (Dockerfile, multi-stage, compose, nginx, postgres, redis) - linux/: 12 referencias de shell/bash (find, grep, awk, sed, processos, cron, systemd) Todos os arquivos possuem comentarios linha-a-linha em portugues.
This commit is contained in:
parent
1d58d16a08
commit
1e1c35fd90
69 changed files with 2643 additions and 0 deletions
25
exemplos/docker/01_python_basico/Dockerfile
Normal file
25
exemplos/docker/01_python_basico/Dockerfile
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Exemplo 1: Dockerfile basico para uma aplicacao Python
|
||||
# Mostra a estrutura minima de um Dockerfile funcional.
|
||||
# Obs: comentarios em Dockerfile precisam ficar em linhas proprias (nao funcionam apos instrucoes).
|
||||
|
||||
# Imagem base oficial do Python na variante "slim" (menor que a padrao).
|
||||
FROM python:3.12-slim
|
||||
|
||||
# Define o diretorio de trabalho dentro do container (criado se nao existir).
|
||||
WORKDIR /app
|
||||
|
||||
# Copia apenas o requirements.txt primeiro para aproveitar o cache de camadas:
|
||||
# se o codigo mudar mas as dependencias nao, esta camada e reaproveitada.
|
||||
COPY requirements.txt .
|
||||
|
||||
# Instala as dependencias sem deixar cache do pip (reduz o tamanho da imagem).
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copia todo o codigo da aplicacao para /app no container.
|
||||
COPY . .
|
||||
|
||||
# Documenta que o container escuta na porta 5000 (apenas informativo, nao publica a porta).
|
||||
EXPOSE 5000
|
||||
|
||||
# Comando padrao executado quando o container inicia.
|
||||
CMD ["python", "app.py"]
|
||||
11
exemplos/docker/01_python_basico/README.md
Normal file
11
exemplos/docker/01_python_basico/README.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# 01 - Dockerfile Python Basico
|
||||
|
||||
Estrutura minima para containerizar uma app Python (Flask).
|
||||
|
||||
## Comandos
|
||||
|
||||
```bash
|
||||
docker build -t app-basico . # Constroi a imagem a partir do Dockerfile, com a tag "app-basico"
|
||||
docker run -p 5000:5000 app-basico # Executa o container mapeando a porta 5000 do host para 5000 do container
|
||||
curl http://localhost:5000 # Testa a aplicacao
|
||||
```
|
||||
12
exemplos/docker/01_python_basico/app.py
Normal file
12
exemplos/docker/01_python_basico/app.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Aplicacao Flask minima usada pelo Dockerfile deste exemplo.
|
||||
|
||||
from flask import Flask # Importa a classe Flask para criar a aplicacao web
|
||||
|
||||
app = Flask(__name__) # Cria a instancia da aplicacao Flask
|
||||
|
||||
@app.route("/") # Decorator que mapeia a URL "/" para a funcao abaixo
|
||||
def home(): # Funcao executada quando alguem acessa a raiz
|
||||
return "Ola do container Docker!" # Resposta HTTP em texto puro
|
||||
|
||||
if __name__ == "__main__": # So executa quando rodado diretamente
|
||||
app.run(host="0.0.0.0", port=5000) # Escuta em todas as interfaces para ser acessivel fora do container
|
||||
1
exemplos/docker/01_python_basico/requirements.txt
Normal file
1
exemplos/docker/01_python_basico/requirements.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
flask==3.0.0
|
||||
53
exemplos/docker/02_python_multistage/Dockerfile
Normal file
53
exemplos/docker/02_python_multistage/Dockerfile
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Exemplo 2: Multi-stage build em Python
|
||||
# Tecnica que separa a fase de "build" da fase de "runtime" para gerar imagens
|
||||
# menores e mais seguras. O estagio "builder" e descartado da imagem final.
|
||||
|
||||
# ---------- ESTAGIO 1: BUILDER ----------
|
||||
|
||||
# Primeiro estagio nomeado "builder" - sera descartado no final da build.
|
||||
FROM python:3.12-slim AS builder
|
||||
|
||||
# Diretorio de trabalho do builder.
|
||||
WORKDIR /app
|
||||
|
||||
# Instala o compilador GCC (necessario para compilar wheels nativos como cryptography, numpy, etc).
|
||||
# Em seguida limpa o cache do apt para nao inflar a camada.
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends gcc \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copia apenas o requirements para aproveitar cache.
|
||||
COPY requirements.txt .
|
||||
|
||||
# Instala em modo --user para que tudo va para /root/.local
|
||||
# (assim podemos copiar APENAS isso para o estagio final).
|
||||
RUN pip install --user --no-cache-dir -r requirements.txt
|
||||
|
||||
# ---------- ESTAGIO 2: RUNTIME ----------
|
||||
|
||||
# Segundo estagio: imagem final, mais limpa (sem gcc, sem cache, sem ferramentas de build).
|
||||
FROM python:3.12-slim
|
||||
|
||||
# Diretorio de trabalho da imagem final.
|
||||
WORKDIR /app
|
||||
|
||||
# Copia APENAS as dependencias instaladas do estagio anterior.
|
||||
COPY --from=builder /root/.local /root/.local
|
||||
|
||||
# Copia o codigo da aplicacao.
|
||||
COPY . .
|
||||
|
||||
# Adiciona o diretorio de binarios do pip-user ao PATH.
|
||||
ENV PATH=/root/.local/bin:$PATH
|
||||
|
||||
# Cria um usuario nao-root chamado "appuser" para rodar a app (boa pratica de seguranca).
|
||||
RUN useradd --create-home appuser
|
||||
|
||||
# Troca para o usuario nao-privilegiado.
|
||||
USER appuser
|
||||
|
||||
# Documenta a porta da aplicacao.
|
||||
EXPOSE 8000
|
||||
|
||||
# Comando padrao do container.
|
||||
CMD ["python", "app.py"]
|
||||
15
exemplos/docker/02_python_multistage/README.md
Normal file
15
exemplos/docker/02_python_multistage/README.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# 02 - Multi-stage Build (Python)
|
||||
|
||||
Demonstra como reduzir o tamanho da imagem final separando ferramentas de build (compiladores) das dependencias de runtime, e como rodar com usuario nao-root.
|
||||
|
||||
## Beneficios
|
||||
|
||||
- Imagem final menor (sem `gcc`, sem cache do apt)
|
||||
- Mais segura (usuario nao-root, sem ferramentas de build)
|
||||
- Cache de build aproveitado entre rebuilds
|
||||
|
||||
## Comando
|
||||
|
||||
```bash
|
||||
docker build -t app-multistage .
|
||||
```
|
||||
31
exemplos/docker/03_node_app/Dockerfile
Normal file
31
exemplos/docker/03_node_app/Dockerfile
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Exemplo 3: Dockerfile para aplicacao Node.js
|
||||
# Mostra padroes especificos do ecossistema JavaScript.
|
||||
|
||||
# Usa Node 20 sobre Alpine Linux (imagem muito pequena, ~50MB).
|
||||
FROM node:20-alpine
|
||||
|
||||
# Convencao comum para apps Node em containers.
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Copia package.json E package-lock.json (o "*" faz o match) ANTES do codigo,
|
||||
# para que o "npm ci" so seja reexecutado quando as dependencias mudarem.
|
||||
COPY package*.json ./
|
||||
|
||||
# "npm ci" e mais rapido e determinista que "npm install" e respeita o lockfile.
|
||||
# "--only=production" ignora devDependencies.
|
||||
RUN npm ci --only=production
|
||||
|
||||
# Copia o restante do codigo.
|
||||
COPY . .
|
||||
|
||||
# Define variavel de ambiente NODE_ENV (Express e outras libs otimizam quando ela e "production").
|
||||
ENV NODE_ENV=production
|
||||
|
||||
# Documenta a porta usada pelo servidor.
|
||||
EXPOSE 3000
|
||||
|
||||
# A imagem oficial do Node ja vem com um usuario "node" pre-criado - usamos por seguranca.
|
||||
USER node
|
||||
|
||||
# Comando para iniciar a aplicacao.
|
||||
CMD ["node", "index.js"]
|
||||
12
exemplos/docker/03_node_app/index.js
Normal file
12
exemplos/docker/03_node_app/index.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Servidor HTTP minimo em Node.js puro (sem dependencias externas).
|
||||
|
||||
const http = require('http'); // Importa o modulo nativo de HTTP do Node
|
||||
|
||||
const server = http.createServer((req, res) => { // Cria o servidor com um handler de requisicoes
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' }); // Define status 200 e content-type texto puro
|
||||
res.end('Ola do Node.js dentro do Docker!\n'); // Envia a resposta e finaliza
|
||||
});
|
||||
|
||||
server.listen(3000, '0.0.0.0', () => { // Escuta na porta 3000 em todas as interfaces (necessario no Docker)
|
||||
console.log('Servidor rodando em http://0.0.0.0:3000'); // Log de inicializacao
|
||||
});
|
||||
9
exemplos/docker/03_node_app/package.json
Normal file
9
exemplos/docker/03_node_app/package.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "node-docker-exemplo",
|
||||
"version": "1.0.0",
|
||||
"description": "Exemplo de aplicacao Node.js containerizada",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
}
|
||||
}
|
||||
19
exemplos/docker/04_compose_app_db/README.md
Normal file
19
exemplos/docker/04_compose_app_db/README.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# 04 - docker-compose: App + Banco
|
||||
|
||||
Demonstra orquestracao de dois servicos (app web + PostgreSQL) com rede compartilhada interna, variaveis de ambiente, volume persistente e politica de restart.
|
||||
|
||||
## Comandos
|
||||
|
||||
```bash
|
||||
docker compose up -d # Sobe os servicos em background
|
||||
docker compose ps # Lista o status dos containers
|
||||
docker compose logs -f web # Acompanha logs do servico "web"
|
||||
docker compose down # Para e remove containers (mantem volume)
|
||||
docker compose down -v # Para e remove ATE os volumes (apaga dados!)
|
||||
```
|
||||
|
||||
## Pontos-chave
|
||||
|
||||
- O hostname `db` e resolvido automaticamente pela rede interna do compose
|
||||
- `depends_on` controla ordem mas NAO espera o banco estar "pronto" (use healthcheck para isso)
|
||||
- O volume `pgdata` sobrevive a `docker compose down` (mas nao a `down -v`)
|
||||
22
exemplos/docker/04_compose_app_db/app/Dockerfile
Normal file
22
exemplos/docker/04_compose_app_db/app/Dockerfile
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Dockerfile da aplicacao usada pelo docker-compose deste exemplo.
|
||||
|
||||
# Imagem base Python.
|
||||
FROM python:3.12-slim
|
||||
|
||||
# Diretorio de trabalho.
|
||||
WORKDIR /app
|
||||
|
||||
# Copia dependencias.
|
||||
COPY requirements.txt .
|
||||
|
||||
# Instala dependencias sem cache.
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copia o codigo.
|
||||
COPY . .
|
||||
|
||||
# Documenta a porta exposta.
|
||||
EXPOSE 8000
|
||||
|
||||
# Comando default.
|
||||
CMD ["python", "main.py"]
|
||||
18
exemplos/docker/04_compose_app_db/app/main.py
Normal file
18
exemplos/docker/04_compose_app_db/app/main.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Aplicacao stub que apenas le a variavel de ambiente DATABASE_URL e responde.
|
||||
|
||||
import os # Modulo para ler variaveis de ambiente
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler # Servidor HTTP minimo da stdlib
|
||||
|
||||
DATABASE_URL = os.environ.get("DATABASE_URL", "nao definido") # Le a URL do banco injetada via compose
|
||||
|
||||
class Handler(BaseHTTPRequestHandler): # Handler de requisicoes HTTP
|
||||
def do_GET(self): # Trata requisicoes GET
|
||||
self.send_response(200) # Status HTTP 200
|
||||
self.send_header("Content-Type", "text/plain") # Resposta em texto puro
|
||||
self.end_headers() # Finaliza os headers
|
||||
self.wfile.write(f"Conectado em: {DATABASE_URL}\n".encode()) # Escreve corpo da resposta
|
||||
|
||||
if __name__ == "__main__": # Bloco de inicializacao
|
||||
servidor = HTTPServer(("0.0.0.0", 8000), Handler) # Cria servidor na porta 8000
|
||||
print("Servidor ouvindo em 0.0.0.0:8000") # Log
|
||||
servidor.serve_forever() # Roda em loop
|
||||
1
exemplos/docker/04_compose_app_db/app/requirements.txt
Normal file
1
exemplos/docker/04_compose_app_db/app/requirements.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Sem dependencias externas - usamos apenas a biblioteca padrao
|
||||
30
exemplos/docker/04_compose_app_db/docker-compose.yml
Normal file
30
exemplos/docker/04_compose_app_db/docker-compose.yml
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Exemplo 4: docker-compose com aplicacao + banco de dados
|
||||
# Demonstra orquestracao de multiplos containers com dependencias e rede compartilhada.
|
||||
|
||||
version: "3.9" # Versao do formato compose (3.9 e amplamente compativel)
|
||||
|
||||
services: # Bloco onde declaramos cada container
|
||||
web: # Nome do servico da aplicacao (acessivel por outros containers via "web")
|
||||
build: ./app # Constroi a imagem a partir do Dockerfile dentro de ./app
|
||||
ports: # Mapeamento de portas host:container
|
||||
- "8000:8000" # Porta 8000 do host expoe a 8000 do container
|
||||
environment: # Variaveis de ambiente injetadas no container
|
||||
DATABASE_URL: postgres://user:senha@db:5432/appdb # "db" e o hostname do servico postgres (DNS interno do compose)
|
||||
depends_on: # Define ordem de inicializacao
|
||||
- db # Espera o servico "db" iniciar antes de subir o "web"
|
||||
restart: unless-stopped # Reinicia automaticamente, exceto se parado manualmente
|
||||
|
||||
db: # Servico do banco de dados PostgreSQL
|
||||
image: postgres:16-alpine # Imagem oficial do Postgres em variante Alpine (menor)
|
||||
environment: # Variaveis usadas pelo entrypoint do Postgres para criar usuario/banco inicial
|
||||
POSTGRES_USER: user # Usuario do banco
|
||||
POSTGRES_PASSWORD: senha # Senha do usuario
|
||||
POSTGRES_DB: appdb # Nome do banco a ser criado na inicializacao
|
||||
volumes: # Volumes persistentes
|
||||
- pgdata:/var/lib/postgresql/data # Persiste os dados do banco fora do ciclo de vida do container
|
||||
ports: # Expoe a porta para debug local (opcional em prod)
|
||||
- "5432:5432" # Porta padrao do Postgres
|
||||
restart: unless-stopped # Politica de reinicio
|
||||
|
||||
volumes: # Declaracao dos volumes nomeados
|
||||
pgdata: # Volume gerenciado pelo Docker que mantem os dados do banco
|
||||
20
exemplos/docker/05_nginx_static/Dockerfile
Normal file
20
exemplos/docker/05_nginx_static/Dockerfile
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Exemplo 5: Servindo arquivos estaticos com Nginx
|
||||
# Caso classico para hospedar sites estaticos (HTML/CSS/JS) ou SPAs (React/Vue/Angular).
|
||||
|
||||
# Imagem oficial do Nginx em variante Alpine (super leve, ~25MB).
|
||||
FROM nginx:alpine
|
||||
|
||||
# Remove a pagina default do Nginx para nao confundir.
|
||||
RUN rm -rf /usr/share/nginx/html/*
|
||||
|
||||
# Copia o conteudo estatico para o diretorio padrao que o Nginx serve.
|
||||
COPY html/ /usr/share/nginx/html/
|
||||
|
||||
# Copia uma configuracao customizada do Nginx (sobrescreve a default).
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Porta padrao do Nginx.
|
||||
EXPOSE 80
|
||||
|
||||
# A imagem ja tem um CMD que roda o nginx em foreground, mas deixamos explicito.
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
11
exemplos/docker/05_nginx_static/html/index.html
Normal file
11
exemplos/docker/05_nginx_static/html/index.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Site estatico no Docker</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Funcionando!</h1>
|
||||
<p>Esta pagina e servida por Nginx dentro de um container Docker.</p>
|
||||
</body>
|
||||
</html>
|
||||
25
exemplos/docker/05_nginx_static/nginx.conf
Normal file
25
exemplos/docker/05_nginx_static/nginx.conf
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Configuracao customizada do Nginx para servir arquivos estaticos.
|
||||
|
||||
server {
|
||||
# Porta interna em que o Nginx vai escutar.
|
||||
listen 80;
|
||||
|
||||
# Nome do servidor (qualquer host ou localhost).
|
||||
server_name _;
|
||||
|
||||
# Diretorio raiz que contem os arquivos estaticos.
|
||||
root /usr/share/nginx/html;
|
||||
|
||||
# Lista de arquivos default servidos quando a URL termina em "/".
|
||||
index index.html;
|
||||
|
||||
# Bloco principal de roteamento.
|
||||
location / {
|
||||
# try_files tenta servir o arquivo solicitado; se nao existir, serve o index.html.
|
||||
# Esse padrao e essencial para SPAs (React Router, Vue Router etc).
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Pagina customizada de erro 404.
|
||||
error_page 404 /404.html;
|
||||
}
|
||||
14
exemplos/docker/06_compose_fullstack/api/Dockerfile
Normal file
14
exemplos/docker/06_compose_fullstack/api/Dockerfile
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Dockerfile da API Python usada no exemplo fullstack.
|
||||
|
||||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY . .
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["python", "main.py"]
|
||||
18
exemplos/docker/06_compose_fullstack/api/main.py
Normal file
18
exemplos/docker/06_compose_fullstack/api/main.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# API stub que reporta as variaveis de ambiente injetadas pelo compose.
|
||||
|
||||
import os # Para ler variaveis de ambiente
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler # Servidor HTTP da stdlib
|
||||
|
||||
DATABASE_URL = os.environ.get("DATABASE_URL", "nao definido") # URL do banco
|
||||
REDIS_URL = os.environ.get("REDIS_URL", "nao definido") # URL do Redis
|
||||
|
||||
class Handler(BaseHTTPRequestHandler): # Handler de requisicoes
|
||||
def do_GET(self): # Trata GET
|
||||
self.send_response(200) # Status 200
|
||||
self.send_header("Content-Type", "text/plain") # Texto puro
|
||||
self.end_headers() # Fim dos headers
|
||||
corpo = f"DB: {DATABASE_URL}\nREDIS: {REDIS_URL}\n" # Monta corpo da resposta
|
||||
self.wfile.write(corpo.encode()) # Envia
|
||||
|
||||
if __name__ == "__main__": # Inicializacao
|
||||
HTTPServer(("0.0.0.0", 8000), Handler).serve_forever() # Roda na porta 8000
|
||||
|
|
@ -0,0 +1 @@
|
|||
# Sem dependencias externas - usamos apenas a biblioteca padrao do Python.
|
||||
81
exemplos/docker/06_compose_fullstack/docker-compose.yml
Normal file
81
exemplos/docker/06_compose_fullstack/docker-compose.yml
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Exemplo 6: docker-compose fullstack (frontend + backend + banco + cache)
|
||||
# Mostra como orquestrar uma stack tipica com Nginx -> API Python -> Postgres + Redis.
|
||||
|
||||
version: "3.9"
|
||||
|
||||
# Rede customizada compartilhada por todos os servicos.
|
||||
# Por padrao o compose ja cria uma, mas declarar explicitamente da mais controle.
|
||||
networks:
|
||||
appnet:
|
||||
driver: bridge
|
||||
|
||||
# Volumes nomeados para persistencia.
|
||||
volumes:
|
||||
postgres_data:
|
||||
redis_data:
|
||||
|
||||
services:
|
||||
# ---------- FRONTEND (Nginx reverse proxy) ----------
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
# Mapeia 80 do host para 80 do container - ponto de entrada publico.
|
||||
- "80:80"
|
||||
volumes:
|
||||
# Configuracao do reverse proxy (readonly por seguranca).
|
||||
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
depends_on:
|
||||
- api
|
||||
networks:
|
||||
- appnet
|
||||
restart: unless-stopped
|
||||
|
||||
# ---------- BACKEND (API Python) ----------
|
||||
api:
|
||||
build: ./api
|
||||
environment:
|
||||
# Hostnames "db" e "cache" sao resolvidos pela rede do compose.
|
||||
DATABASE_URL: postgres://user:senha@db:5432/appdb
|
||||
REDIS_URL: redis://cache:6379/0
|
||||
depends_on:
|
||||
db:
|
||||
# condition: service_healthy espera o healthcheck passar antes de subir esta dependencia.
|
||||
condition: service_healthy
|
||||
cache:
|
||||
condition: service_started
|
||||
networks:
|
||||
- appnet
|
||||
restart: unless-stopped
|
||||
|
||||
# ---------- BANCO DE DADOS (Postgres) ----------
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_USER: user
|
||||
POSTGRES_PASSWORD: senha
|
||||
POSTGRES_DB: appdb
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
# Comando que verifica se o banco esta pronto para aceitar conexoes.
|
||||
test: ["CMD-SHELL", "pg_isready -U user -d appdb"]
|
||||
# Frequencia da checagem.
|
||||
interval: 5s
|
||||
# Tempo maximo para o comando responder.
|
||||
timeout: 5s
|
||||
# Quantas tentativas antes de marcar como unhealthy.
|
||||
retries: 5
|
||||
networks:
|
||||
- appnet
|
||||
restart: unless-stopped
|
||||
|
||||
# ---------- CACHE (Redis) ----------
|
||||
cache:
|
||||
image: redis:7-alpine
|
||||
# Comando customizado: habilita persistencia AOF para nao perder dados em restart.
|
||||
command: redis-server --appendonly yes
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
networks:
|
||||
- appnet
|
||||
restart: unless-stopped
|
||||
24
exemplos/docker/06_compose_fullstack/nginx.conf
Normal file
24
exemplos/docker/06_compose_fullstack/nginx.conf
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Configuracao Nginx como reverse proxy para a API.
|
||||
|
||||
# Bloco upstream define o pool de backends - aqui apenas o servico "api".
|
||||
upstream backend {
|
||||
# "api" e o hostname do servico no compose, e ele escuta na porta 8000.
|
||||
server api:8000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
# Toda requisicao em "/" e encaminhada para o backend.
|
||||
location / {
|
||||
# Passa a requisicao para o upstream definido acima.
|
||||
proxy_pass http://backend;
|
||||
|
||||
# Headers necessarios para o backend saber o IP/host originais.
|
||||
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;
|
||||
}
|
||||
}
|
||||
17
exemplos/docker/07_postgres_persistente/README.md
Normal file
17
exemplos/docker/07_postgres_persistente/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# 07 - Postgres com Volume Persistente
|
||||
|
||||
## Comandos uteis
|
||||
|
||||
```bash
|
||||
docker compose up -d # Sobe o banco em background
|
||||
docker compose exec db psql -U admin minhabase # Abre o psql dentro do container
|
||||
docker compose logs -f db # Acompanha logs
|
||||
docker compose down # Para o container (mantem dados!)
|
||||
docker compose down -v # Para E remove o volume (apaga dados)
|
||||
```
|
||||
|
||||
## Como funciona o seed
|
||||
|
||||
A pasta `./init` e montada em `/docker-entrypoint-initdb.d`. O entrypoint do Postgres executa todos os `.sql` e `.sh` desse diretorio em ordem alfabetica, **mas apenas se o volume estiver vazio**. Por isso usamos prefixos numericos: `01_schema.sql`, `02_seed.sql`, etc.
|
||||
|
||||
Se voce mudar o SQL e quiser reaplicar, precisa apagar o volume primeiro com `docker compose down -v`.
|
||||
29
exemplos/docker/07_postgres_persistente/docker-compose.yml
Normal file
29
exemplos/docker/07_postgres_persistente/docker-compose.yml
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Exemplo 7: Postgres com volume persistente e script de inicializacao
|
||||
# Demonstra como popular o banco automaticamente na primeira execucao.
|
||||
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
container_name: postgres_persistente
|
||||
environment:
|
||||
POSTGRES_USER: admin
|
||||
POSTGRES_PASSWORD: admin
|
||||
POSTGRES_DB: minhabase
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
# Volume nomeado para persistencia dos dados.
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
# Diretorio especial: scripts .sql ou .sh aqui sao executados na PRIMEIRA inicializacao do banco.
|
||||
# Se o volume "postgres_data" ja contiver um banco, esses scripts NAO sao reexecutados.
|
||||
- ./init:/docker-entrypoint-initdb.d:ro
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U admin -d minhabase"]
|
||||
interval: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
16
exemplos/docker/07_postgres_persistente/init/01_schema.sql
Normal file
16
exemplos/docker/07_postgres_persistente/init/01_schema.sql
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
-- Script executado APENAS na primeira inicializacao do banco (quando o volume esta vazio).
|
||||
-- Cria uma tabela de exemplo e insere alguns registros.
|
||||
|
||||
-- Cria a tabela "usuarios" se ela ainda nao existir.
|
||||
CREATE TABLE IF NOT EXISTS usuarios (
|
||||
id SERIAL PRIMARY KEY, -- Chave primaria com auto-incremento
|
||||
nome VARCHAR(100) NOT NULL, -- Nome do usuario, nao nulo
|
||||
email VARCHAR(150) UNIQUE NOT NULL, -- Email unico, nao nulo
|
||||
criado_em TIMESTAMP DEFAULT NOW() -- Data de criacao com default no momento do insert
|
||||
);
|
||||
|
||||
-- Insere alguns registros iniciais (seed).
|
||||
INSERT INTO usuarios (nome, email) VALUES
|
||||
('Alice', 'alice@exemplo.com'),
|
||||
('Bob', 'bob@exemplo.com'),
|
||||
('Carol', 'carol@exemplo.com');
|
||||
17
exemplos/docker/08_redis_cache/README.md
Normal file
17
exemplos/docker/08_redis_cache/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# 08 - Redis com Persistencia e Autenticacao
|
||||
|
||||
## Comandos uteis
|
||||
|
||||
```bash
|
||||
docker compose up -d # Sobe o Redis
|
||||
docker compose exec redis redis-cli -a senha_super_secreta # Abre o redis-cli autenticado
|
||||
docker compose exec redis redis-cli -a senha_super_secreta PING # Testa conexao (retorna PONG)
|
||||
```
|
||||
|
||||
## Politicas de eviction (maxmemory-policy)
|
||||
|
||||
- `noeviction` -> rejeita novas escritas quando atinge limite (cuidado!)
|
||||
- `allkeys-lru` -> remove as menos recentemente usadas (cache geral)
|
||||
- `volatile-lru` -> mesma coisa, mas apenas chaves com TTL
|
||||
- `allkeys-random` -> remove qualquer chave aleatoriamente
|
||||
- `volatile-ttl` -> remove as com TTL mais proximo de expirar
|
||||
34
exemplos/docker/08_redis_cache/docker-compose.yml
Normal file
34
exemplos/docker/08_redis_cache/docker-compose.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Exemplo 8: Redis com persistencia + senha + memoria limitada
|
||||
# Configuracao tipica de cache para producao.
|
||||
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: redis_cache
|
||||
ports:
|
||||
- "6379:6379"
|
||||
# Argumentos passados para o redis-server:
|
||||
# --requirepass -> exige senha em todas as conexoes
|
||||
# --appendonly -> habilita persistencia AOF (append-only file)
|
||||
# --maxmemory -> limita uso de RAM
|
||||
# --maxmemory-policy allkeys-lru -> quando atingir o limite, remove as chaves menos usadas (LRU)
|
||||
command: >
|
||||
redis-server
|
||||
--requirepass senha_super_secreta
|
||||
--appendonly yes
|
||||
--maxmemory 256mb
|
||||
--maxmemory-policy allkeys-lru
|
||||
volumes:
|
||||
# Persistencia dos arquivos AOF/RDB.
|
||||
- redis_data:/data
|
||||
healthcheck:
|
||||
# PING via redis-cli, autenticando com a senha.
|
||||
test: ["CMD", "redis-cli", "-a", "senha_super_secreta", "ping"]
|
||||
interval: 10s
|
||||
retries: 3
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
redis_data:
|
||||
61
exemplos/docker/09_dockerignore_exemplo/.dockerignore
Normal file
61
exemplos/docker/09_dockerignore_exemplo/.dockerignore
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Exemplo 9: arquivo .dockerignore
|
||||
# Funciona como o .gitignore mas para o "COPY" do Docker.
|
||||
# Reduz o contexto enviado ao daemon (build mais rapida e imagem menor).
|
||||
|
||||
# ---------- Controle de versao ----------
|
||||
.git
|
||||
.gitignore
|
||||
.gitattributes
|
||||
|
||||
# ---------- Python ----------
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
.Python
|
||||
*.egg-info/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.tox/
|
||||
venv/
|
||||
.venv/
|
||||
env/
|
||||
|
||||
# ---------- Node.js ----------
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# ---------- Editores e IDEs ----------
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
.DS_Store
|
||||
|
||||
# ---------- Variaveis de ambiente e segredos ----------
|
||||
# CRITICO: nunca copie .env para dentro da imagem!
|
||||
.env
|
||||
.env.*
|
||||
*.pem
|
||||
*.key
|
||||
secrets/
|
||||
|
||||
# ---------- Build e dist ----------
|
||||
dist/
|
||||
build/
|
||||
*.log
|
||||
|
||||
# ---------- Arquivos do proprio Docker ----------
|
||||
# Evita copiar o Dockerfile dentro da imagem (raramente faz sentido).
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
.dockerignore
|
||||
|
||||
# ---------- Testes e documentacao ----------
|
||||
# Em prod normalmente nao precisamos de testes/docs dentro da imagem.
|
||||
tests/
|
||||
docs/
|
||||
*.md
|
||||
README*
|
||||
21
exemplos/docker/09_dockerignore_exemplo/README.md
Normal file
21
exemplos/docker/09_dockerignore_exemplo/README.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# 09 - Exemplo de .dockerignore
|
||||
|
||||
O `.dockerignore` define padroes de arquivos/pastas que serao **excluidos** do contexto enviado ao Docker daemon durante o `docker build`.
|
||||
|
||||
## Por que e importante
|
||||
|
||||
1. **Performance**: builds mais rapidas (contexto menor)
|
||||
2. **Imagens menores**: nao copia `node_modules`, `.git`, etc, mesmo com `COPY . .`
|
||||
3. **Seguranca**: evita vazar arquivos sensiveis (`.env`, chaves, credenciais)
|
||||
4. **Cache invalidation**: arquivos voluveis (ex: logs) nao quebram o cache de camadas
|
||||
|
||||
## Como usar
|
||||
|
||||
Coloque o arquivo `.dockerignore` na raiz do contexto (mesmo nivel do `Dockerfile`). O Docker o le automaticamente.
|
||||
|
||||
## Sintaxe
|
||||
|
||||
Identica ao `.gitignore`:
|
||||
- `*.log` -> qualquer arquivo `.log`
|
||||
- `node_modules/` -> diretorio inteiro
|
||||
- `!important.log` -> EXCECAO (nao ignorar este)
|
||||
49
exemplos/docker/README.md
Normal file
49
exemplos/docker/README.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Exemplos Docker
|
||||
|
||||
Colecao de exemplos comentados linha-a-linha em portugues, cobrindo cenarios comuns de containerizacao.
|
||||
|
||||
## Indice
|
||||
|
||||
| # | Pasta | Topico |
|
||||
|---|-------|--------|
|
||||
| 01 | `01_python_basico/` | Dockerfile minimo para app Python (Flask) |
|
||||
| 02 | `02_python_multistage/` | Multi-stage build + usuario nao-root |
|
||||
| 03 | `03_node_app/` | Dockerfile para Node.js (Alpine) |
|
||||
| 04 | `04_compose_app_db/` | docker-compose com app + Postgres |
|
||||
| 05 | `05_nginx_static/` | Servindo site estatico/SPA com Nginx |
|
||||
| 06 | `06_compose_fullstack/` | Stack Nginx + API + Postgres + Redis |
|
||||
| 07 | `07_postgres_persistente/` | Postgres com volume + script de seed |
|
||||
| 08 | `08_redis_cache/` | Redis com senha, AOF e politica LRU |
|
||||
| 09 | `09_dockerignore_exemplo/` | Exemplo completo de `.dockerignore` |
|
||||
|
||||
## Comandos essenciais
|
||||
|
||||
```bash
|
||||
# Build e run de uma imagem
|
||||
docker build -t minha-app .
|
||||
docker run -p 8000:8000 minha-app
|
||||
|
||||
# docker compose (V2 - sem hifen)
|
||||
docker compose up -d # Sobe servicos em background
|
||||
docker compose ps # Status dos containers
|
||||
docker compose logs -f # Acompanha logs de todos servicos
|
||||
docker compose down # Para e remove containers
|
||||
docker compose down -v # Tambem remove volumes (CUIDADO: apaga dados)
|
||||
|
||||
# Inspecao
|
||||
docker ps # Containers rodando
|
||||
docker images # Imagens locais
|
||||
docker exec -it <container> sh # Shell dentro do container
|
||||
|
||||
# Limpeza
|
||||
docker system prune # Remove containers parados, redes nao usadas, etc
|
||||
docker system prune -a --volumes # Remove TUDO que nao esta em uso (cuidado)
|
||||
```
|
||||
|
||||
## Observacoes importantes
|
||||
|
||||
- **Comentarios em Dockerfile** precisam ficar em **linha propria**. Inline (`COPY . . # comentario`) NAO funciona em todas as instrucoes.
|
||||
- **Camadas e cache**: a ordem das instrucoes importa. Copie arquivos voluveis (codigo) **depois** de instalar dependencias.
|
||||
- **Sempre use** `.dockerignore` para evitar inflar o contexto e vazar segredos.
|
||||
- **Nao rode como root** em producao: crie um usuario nao-privilegiado (`USER appuser`).
|
||||
- **Multi-stage builds** sao a forma padrao moderna de obter imagens pequenas e seguras.
|
||||
52
exemplos/linux/01_basico_arquivos.sh
Executable file
52
exemplos/linux/01_basico_arquivos.sh
Executable file
|
|
@ -0,0 +1,52 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 1: Operacoes basicas com arquivos e diretorios
|
||||
# Comandos essenciais que todo desenvolvedor precisa dominar.
|
||||
|
||||
# ---------- LISTAGEM ----------
|
||||
|
||||
ls # Lista arquivos do diretorio atual (so nomes)
|
||||
ls -l # Lista detalhada (permissoes, dono, tamanho, data)
|
||||
ls -la # Inclui arquivos ocultos (comecam com .)
|
||||
ls -lh # Tamanhos em formato legivel (K, M, G)
|
||||
ls -lt # Ordena por data de modificacao (mais novo primeiro)
|
||||
ls -lS # Ordena por tamanho (maior primeiro)
|
||||
|
||||
# ---------- NAVEGACAO ----------
|
||||
|
||||
pwd # Mostra o caminho absoluto do diretorio atual
|
||||
cd /tmp # Muda para o diretorio /tmp
|
||||
cd ~ # Vai para o diretorio HOME do usuario
|
||||
cd - # Volta para o diretorio anterior (toggle)
|
||||
cd .. # Sobe um nivel na arvore
|
||||
|
||||
# ---------- CRIACAO ----------
|
||||
|
||||
mkdir nova_pasta # Cria um diretorio
|
||||
mkdir -p a/b/c # Cria a estrutura inteira (incluindo intermediarios)
|
||||
touch arquivo.txt # Cria arquivo vazio (ou atualiza timestamp se existir)
|
||||
|
||||
# ---------- COPIA E MOVIMENTACAO ----------
|
||||
|
||||
cp origem.txt destino.txt # Copia arquivo
|
||||
cp -r pasta1 pasta2 # Copia diretorio RECURSIVAMENTE (-r essencial!)
|
||||
cp -i a.txt b.txt # -i pergunta antes de sobrescrever (seguranca)
|
||||
mv antigo.txt novo.txt # Renomeia (mover dentro do mesmo dir)
|
||||
mv arquivo.txt /tmp/ # Move para outro diretorio
|
||||
|
||||
# ---------- REMOCAO ----------
|
||||
|
||||
rm arquivo.txt # Remove arquivo
|
||||
rm -i arquivo.txt # -i pergunta confirmacao (recomendado)
|
||||
rm -r diretorio/ # Remove diretorio e conteudo recursivamente
|
||||
# CUIDADO: "rm -rf /" e o classico comando destrutivo - NUNCA execute sem entender!
|
||||
rmdir pasta_vazia # Remove apenas se o diretorio estiver vazio (mais seguro)
|
||||
|
||||
# ---------- VISUALIZACAO ----------
|
||||
|
||||
cat arquivo.txt # Mostra o conteudo inteiro de uma vez
|
||||
less arquivo.txt # Paginado (use q para sair, / para buscar)
|
||||
head arquivo.txt # Primeiras 10 linhas
|
||||
head -n 20 arquivo.txt # Primeiras 20 linhas
|
||||
tail arquivo.txt # Ultimas 10 linhas
|
||||
tail -f /var/log/syslog # "Follow": acompanha em tempo real (otimo para logs)
|
||||
wc -l arquivo.txt # Conta linhas; -w conta palavras; -c conta bytes
|
||||
57
exemplos/linux/02_permissoes.sh
Executable file
57
exemplos/linux/02_permissoes.sh
Executable file
|
|
@ -0,0 +1,57 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 2: Permissoes de arquivos no Linux
|
||||
# Modelo classico Unix: dono, grupo, outros (rwx para cada).
|
||||
|
||||
# ---------- ENTENDENDO O OUTPUT DO "ls -l" ----------
|
||||
#
|
||||
# -rwxr-xr-- 1 alice devs 1024 May 26 10:00 script.sh
|
||||
# ||||||||| | | | | | |
|
||||
# ||||||||| | | | | | +-- nome
|
||||
# ||||||||| | | | | +--------------- data
|
||||
# ||||||||| | | | +-------------------- tamanho em bytes
|
||||
# ||||||||| | | +------------------------- grupo
|
||||
# ||||||||| | +------------------------------- dono
|
||||
# ||||||||| +--------------------------------- numero de links
|
||||
# ||||||||+----------------------------------- outros (r--)
|
||||
# |||||+-+------------------------------------ grupo (r-x)
|
||||
# ||+-+--------------------------------------- dono (rwx)
|
||||
# +--+----------------------------------------- tipo: - arquivo, d diretorio, l link
|
||||
|
||||
# ---------- CHMOD (mudar permissoes) ----------
|
||||
|
||||
chmod +x script.sh # Adiciona permissao de execucao para todos
|
||||
chmod -x script.sh # Remove permissao de execucao
|
||||
chmod u+x script.sh # Apenas para o USER (dono)
|
||||
chmod g+w arquivo # Adiciona escrita ao GROUP
|
||||
chmod o-r segredo.txt # Remove leitura dos OTHERS
|
||||
|
||||
# Notacao OCTAL (mais comum em scripts):
|
||||
# r=4, w=2, x=1 -> soma para cada categoria
|
||||
chmod 755 script.sh # rwxr-xr-x (dono pode tudo, resto le/executa)
|
||||
chmod 644 documento.txt # rw-r--r-- (dono escreve, resto so le) - padrao para arquivos
|
||||
chmod 700 segredo.txt # rwx------ (so o dono tem acesso)
|
||||
chmod 600 chave_ssh # rw------- (so dono le/escreve) - padrao para chaves
|
||||
chmod -R 755 pasta/ # -R aplica RECURSIVAMENTE
|
||||
|
||||
# ---------- CHOWN (mudar dono) ----------
|
||||
|
||||
sudo chown alice arquivo.txt # Muda o dono para "alice"
|
||||
sudo chown alice:devs arquivo.txt # Muda dono E grupo
|
||||
sudo chown -R www-data:www-data /var/www # Recursivo em todo /var/www
|
||||
|
||||
# ---------- CHGRP (mudar apenas grupo) ----------
|
||||
|
||||
sudo chgrp devs arquivo.txt # Muda apenas o grupo
|
||||
|
||||
# ---------- UMASK (permissoes padrao de novos arquivos) ----------
|
||||
|
||||
umask # Mostra a mask atual (geralmente 022)
|
||||
umask 077 # Define mask: novos arquivos terao apenas permissao do dono
|
||||
# Calculo: arquivos nascem com 666, diretorios com 777, e a mask e SUBTRAIDA.
|
||||
# Mask 022 -> arquivos 644 (666-022), diretorios 755 (777-022).
|
||||
|
||||
# ---------- SUDO (executar como root) ----------
|
||||
|
||||
sudo comando # Roda o comando como root (pede senha)
|
||||
sudo -i # Abre shell como root
|
||||
sudo -u alice comando # Roda como outro usuario (nao root)
|
||||
54
exemplos/linux/03_busca_find_grep.sh
Executable file
54
exemplos/linux/03_busca_find_grep.sh
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 3: Busca de arquivos (find) e busca de conteudo (grep)
|
||||
# Dois dos comandos mais poderosos e cobrados em entrevistas.
|
||||
|
||||
# ---------- FIND (busca por NOME, tipo, tamanho, data) ----------
|
||||
|
||||
find . -name "*.py" # Busca arquivos .py a partir do diretorio atual
|
||||
find . -iname "*.PY" # -iname ignora maiusculas/minusculas
|
||||
find /var/log -type f # -type f = arquivos; -type d = diretorios
|
||||
find . -type d -name "node_modules" # Busca diretorios chamados node_modules
|
||||
find . -size +100M # Arquivos maiores que 100 MB
|
||||
find . -size -1k # Arquivos menores que 1 KB
|
||||
find . -mtime -7 # Modificados nos ultimos 7 dias
|
||||
find . -mtime +30 # Nao modificados ha mais de 30 dias
|
||||
find . -mmin -60 # Modificados na ultima hora
|
||||
find . -user alice # Pertencentes ao usuario "alice"
|
||||
|
||||
# Executar comando em cada resultado:
|
||||
find . -name "*.log" -delete # Deleta cada arquivo encontrado (CUIDADO!)
|
||||
find . -name "*.tmp" -exec rm {} \; # Forma classica: {} e o arquivo, \; finaliza
|
||||
find . -name "*.txt" -exec cat {} + # Com + agrupa todos os args (mais eficiente)
|
||||
find . -name "*.py" | xargs wc -l # Conta linhas de todos os .py (via pipe)
|
||||
|
||||
# ---------- GREP (busca por CONTEUDO dentro de arquivos) ----------
|
||||
|
||||
grep "erro" log.txt # Linhas que contem "erro"
|
||||
grep -i "ERRO" log.txt # -i ignora maiusculas/minusculas
|
||||
grep -r "TODO" . # -r busca recursivamente em diretorios
|
||||
grep -rn "TODO" . # -n mostra numero da linha
|
||||
grep -rl "API_KEY" . # -l so mostra NOMES dos arquivos com match
|
||||
grep -v "DEBUG" log.txt # -v INVERTE: linhas que NAO contem
|
||||
grep -c "erro" log.txt # -c conta linhas com match
|
||||
grep -A 3 "erro" log.txt # -A mostra 3 linhas APOS o match
|
||||
grep -B 3 "erro" log.txt # -B mostra 3 linhas ANTES
|
||||
grep -C 3 "erro" log.txt # -C mostra 3 antes E 3 depois
|
||||
|
||||
# Regex (use -E para extended regex, mais poderoso):
|
||||
grep -E "erro|warning" log.txt # OR: linhas com "erro" OU "warning"
|
||||
grep -E "^[0-9]{4}" arquivo.txt # Linhas comecando com 4 digitos
|
||||
grep -E "[a-z]+@[a-z]+\.com" emails.txt # Padrao simplificado de email
|
||||
|
||||
# Combinacao classica find + grep:
|
||||
find . -name "*.py" -exec grep -l "import os" {} \; # .py que importam os
|
||||
|
||||
# ---------- LOCATE (busca rapida via banco indexado) ----------
|
||||
|
||||
locate arquivo.txt # Busca instantanea no indice (atualizado por updatedb)
|
||||
sudo updatedb # Atualiza o indice manualmente
|
||||
|
||||
# ---------- WHICH / WHEREIS (localizar executaveis) ----------
|
||||
|
||||
which python3 # Caminho do executavel "python3" no PATH
|
||||
whereis python3 # Mostra binario, fonte e manpage
|
||||
type ls # Mostra se e alias, builtin ou arquivo
|
||||
70
exemplos/linux/04_pipes_redirecionamento.sh
Executable file
70
exemplos/linux/04_pipes_redirecionamento.sh
Executable file
|
|
@ -0,0 +1,70 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 4: Pipes (|) e redirecionamento (>, >>, <, 2>)
|
||||
# Conceito central da filosofia Unix: combinar programas pequenos.
|
||||
|
||||
# ---------- REDIRECIONAMENTO DE SAIDA ----------
|
||||
|
||||
ls > saida.txt # Sobrescreve saida.txt com a saida do ls
|
||||
ls >> saida.txt # APPEND: adiciona ao final do arquivo (preserva conteudo)
|
||||
echo "linha" > arquivo.txt # Escreve "linha" no arquivo (sobrescrevendo)
|
||||
|
||||
# ---------- REDIRECIONAMENTO DE ENTRADA ----------
|
||||
|
||||
wc -l < arquivo.txt # Le arquivo.txt como entrada do wc
|
||||
grep "erro" < log.txt # Mesmo que: grep "erro" log.txt
|
||||
|
||||
# ---------- STDERR (canal de erro) ----------
|
||||
|
||||
# Canais: 0 = stdin, 1 = stdout, 2 = stderr
|
||||
comando 2> erros.txt # Redireciona APENAS erros (stderr)
|
||||
comando > saida.txt 2>&1 # Redireciona stdout E stderr para o mesmo arquivo
|
||||
comando &> saida.txt # Forma curta (Bash): tudo para um arquivo
|
||||
comando 2> /dev/null # DESCARTA erros (envia para o "buraco negro")
|
||||
comando > /dev/null 2>&1 # Silencia tudo (sem saida)
|
||||
|
||||
# ---------- PIPE (saida de um comando vira entrada de outro) ----------
|
||||
|
||||
ls -l | grep ".py" # Lista detalhada, filtra so .py
|
||||
ps aux | grep python # Processos que contem "python"
|
||||
cat log.txt | sort | uniq # Pega conteudo, ordena, remove duplicatas
|
||||
history | tail -20 # Ultimos 20 comandos do historico
|
||||
cat /etc/passwd | wc -l # Conta linhas de /etc/passwd (numero de usuarios)
|
||||
|
||||
# ---------- COMBINACOES PODEROSAS ----------
|
||||
|
||||
# Top 5 maiores arquivos do diretorio:
|
||||
du -ah . | sort -rh | head -5
|
||||
|
||||
# Conta linhas de codigo Python no projeto:
|
||||
find . -name "*.py" | xargs wc -l | tail -1
|
||||
|
||||
# Ips que mais aparecem em access.log:
|
||||
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
|
||||
|
||||
# Mata todos processos do firefox:
|
||||
ps aux | grep firefox | awk '{print $2}' | xargs kill
|
||||
|
||||
# ---------- TEE (escreve em arquivo E mostra na tela) ----------
|
||||
|
||||
ls | tee arquivos.txt # Mostra na tela E salva em arquivos.txt
|
||||
ls | tee -a arquivos.txt # -a faz append (nao sobrescreve)
|
||||
comando | tee log.txt | grep "erro" # Salva tudo, mas tambem filtra
|
||||
|
||||
# ---------- COMMAND SUBSTITUTION ----------
|
||||
|
||||
echo "Hoje e $(date)" # $(...) executa o comando e substitui pelo resultado
|
||||
arquivos=$(ls) # Guarda saida do ls na variavel
|
||||
echo "Total: $(ls | wc -l) arquivos" # Aninhado
|
||||
|
||||
# ---------- HEREDOC ----------
|
||||
|
||||
cat << EOF > config.txt
|
||||
linha 1
|
||||
linha 2
|
||||
variavel: $USER
|
||||
EOF
|
||||
# Tudo entre << EOF e EOF e enviado como stdin (com expansao de variaveis).
|
||||
|
||||
cat << 'EOF' > literal.txt
|
||||
$USER nao sera expandido (aspas em EOF desativam expansao)
|
||||
EOF
|
||||
72
exemplos/linux/05_processos.sh
Executable file
72
exemplos/linux/05_processos.sh
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 5: Gerenciamento de processos
|
||||
# Como ver, controlar e matar processos no Linux.
|
||||
|
||||
# ---------- LISTAR PROCESSOS ----------
|
||||
|
||||
ps # Processos do shell atual
|
||||
ps aux # Todos os processos do sistema (formato BSD)
|
||||
ps -ef # Todos, formato System V (mais detalhado)
|
||||
ps aux | grep nginx # Filtra processos do nginx
|
||||
ps -u alice # Processos do usuario "alice"
|
||||
ps --forest # Mostra arvore de processos (parent/child)
|
||||
|
||||
# Colunas mais importantes de "ps aux":
|
||||
# USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
||||
# PID = ID do processo, RSS = memoria fisica em KB, STAT = estado
|
||||
|
||||
# ---------- MONITORAMENTO EM TEMPO REAL ----------
|
||||
|
||||
top # Monitor interativo (q para sair)
|
||||
htop # Versao melhorada (precisa instalar)
|
||||
# Teclas dentro do top:
|
||||
# P = ordena por CPU
|
||||
# M = ordena por memoria
|
||||
# k = mata um processo (pede PID)
|
||||
# q = sair
|
||||
|
||||
# ---------- ENCONTRAR PID DE UM PROCESSO ----------
|
||||
|
||||
pidof nginx # Retorna o(s) PID(s) do processo "nginx"
|
||||
pgrep -f "python app.py" # Busca por linha de comando completa
|
||||
pgrep -u alice # PIDs dos processos da alice
|
||||
|
||||
# ---------- MATAR PROCESSOS ----------
|
||||
|
||||
kill 1234 # Envia SIGTERM (15) - encerramento "educado"
|
||||
kill -9 1234 # SIGKILL (9) - encerramento forcado (ULTIMO RECURSO)
|
||||
kill -15 1234 # SIGTERM explicito (mesmo que kill 1234)
|
||||
kill -1 1234 # SIGHUP - recarregar configuracao (comum em daemons)
|
||||
kill -l # Lista todos os sinais disponiveis
|
||||
|
||||
killall nginx # Mata TODOS processos com nome "nginx"
|
||||
pkill -f "python app.py" # Mata por padrao no command line
|
||||
|
||||
# ---------- SINAIS COMUNS ----------
|
||||
# SIGTERM (15): peca para terminar - permite limpeza
|
||||
# SIGKILL (9): forca terminacao - NAO pode ser ignorado, sem limpeza
|
||||
# SIGHUP (1): hang up - tradicionalmente "recarregue config"
|
||||
# SIGINT (2): interrupcao - igual ao Ctrl+C
|
||||
# SIGSTOP (19): pausa o processo (como Ctrl+Z, mas nao pode ser ignorado)
|
||||
# SIGCONT (18): continua processo pausado
|
||||
|
||||
# ---------- BACKGROUND E FOREGROUND ----------
|
||||
|
||||
comando_longo & # Roda em background; & no final
|
||||
comando_longo # Em foreground; Ctrl+Z pausa, Ctrl+C cancela
|
||||
jobs # Lista jobs do shell atual
|
||||
fg %1 # Traz o job 1 de volta para foreground
|
||||
bg %1 # Continua o job 1 em background
|
||||
|
||||
nohup script.sh & # nohup faz o processo sobreviver ao logout do shell
|
||||
disown %1 # Desvincula o job do shell (similar ao nohup)
|
||||
|
||||
# ---------- INFORMACOES DO SISTEMA ----------
|
||||
|
||||
uptime # Quanto tempo o sistema esta ligado + load average
|
||||
free -h # Memoria livre/usada em formato legivel
|
||||
df -h # Uso de disco por filesystem
|
||||
du -sh /var/log # Tamanho TOTAL do diretorio /var/log
|
||||
uname -a # Info do kernel e sistema
|
||||
lscpu # Detalhes do processador
|
||||
nproc # Numero de cores disponiveis
|
||||
153
exemplos/linux/06_bash_scripting.sh
Executable file
153
exemplos/linux/06_bash_scripting.sh
Executable file
|
|
@ -0,0 +1,153 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 6: Bash scripting - variaveis, condicionais, loops, funcoes
|
||||
# Conhecimento essencial para automacao e DevOps.
|
||||
|
||||
# ---------- SHEBANG ----------
|
||||
# A primeira linha (#!/bin/bash) indica qual interpretador deve rodar o script.
|
||||
# Apos torna-lo executavel (chmod +x), pode ser executado direto: ./script.sh
|
||||
|
||||
# ---------- VARIAVEIS ----------
|
||||
|
||||
nome="Maria" # Sem espacos ao redor do = (importante!)
|
||||
idade=30 # Numeros tambem sao tratados como string em bash
|
||||
echo "Ola, $nome" # $ expande a variavel
|
||||
echo "Ola, ${nome}!" # ${} e mais explicito, util para concatenar: ${nome}_sufixo
|
||||
|
||||
# Variaveis especiais:
|
||||
echo "Script: $0" # Nome do script
|
||||
echo "Primeiro arg: $1" # Primeiro argumento
|
||||
echo "Todos args: $@" # Todos os argumentos
|
||||
echo "Numero de args: $#" # Quantidade de argumentos
|
||||
echo "PID do script: $$" # PID do processo atual
|
||||
echo "Saida ultimo cmd: $?" # Codigo de saida do ultimo comando (0 = sucesso)
|
||||
|
||||
# Variaveis de ambiente:
|
||||
echo $HOME # Diretorio do usuario
|
||||
echo $PATH # Diretorios onde o shell procura executaveis
|
||||
echo $USER # Usuario logado
|
||||
export MINHA_VAR="valor" # Exporta para subprocessos
|
||||
|
||||
# ---------- ENTRADA DO USUARIO ----------
|
||||
|
||||
read -p "Qual seu nome? " nome # -p mostra prompt; le e armazena em "nome"
|
||||
read -s -p "Senha: " senha # -s nao ecoa o que e digitado (para senhas)
|
||||
echo "" # Pula linha apos read -s
|
||||
|
||||
# ---------- CONDICIONAIS ----------
|
||||
|
||||
if [ "$idade" -ge 18 ]; then # -ge = greater or equal (>=)
|
||||
echo "Maior de idade"
|
||||
elif [ "$idade" -ge 12 ]; then # senao se
|
||||
echo "Adolescente"
|
||||
else
|
||||
echo "Crianca"
|
||||
fi # fechamento OBRIGATORIO (if reverso)
|
||||
|
||||
# Operadores numericos: -eq, -ne, -lt, -le, -gt, -ge
|
||||
# Operadores de string: =, !=, -z (vazio), -n (nao vazio)
|
||||
# Operadores de arquivo: -f (arquivo existe), -d (dir existe), -r (legivel)
|
||||
|
||||
if [ -f "config.txt" ]; then # Se o arquivo existe
|
||||
echo "config.txt existe"
|
||||
fi
|
||||
|
||||
if [[ "$nome" == "Maria" ]]; then # [[ ]] e o mais moderno (mais recursos)
|
||||
echo "Ola Maria!"
|
||||
fi
|
||||
|
||||
# ---------- CASE (switch) ----------
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo "Iniciando..."
|
||||
;; # ;; finaliza cada bloco
|
||||
stop)
|
||||
echo "Parando..."
|
||||
;;
|
||||
restart|reload) # | e OR
|
||||
echo "Reiniciando..."
|
||||
;;
|
||||
*) # * e o default
|
||||
echo "Uso: $0 {start|stop|restart}"
|
||||
exit 1 # Sai com codigo 1 (erro)
|
||||
;;
|
||||
esac
|
||||
|
||||
# ---------- LOOPS ----------
|
||||
|
||||
# FOR sobre lista
|
||||
for fruta in maca banana laranja; do
|
||||
echo "Fruta: $fruta"
|
||||
done
|
||||
|
||||
# FOR estilo C (para numeros)
|
||||
for ((i=0; i<5; i++)); do
|
||||
echo "i=$i"
|
||||
done
|
||||
|
||||
# FOR sobre arquivos (glob)
|
||||
for arquivo in *.txt; do
|
||||
echo "Processando $arquivo"
|
||||
done
|
||||
|
||||
# WHILE
|
||||
contador=0
|
||||
while [ $contador -lt 5 ]; do
|
||||
echo "Contador: $contador"
|
||||
contador=$((contador + 1)) # $(( )) e aritmetica
|
||||
done
|
||||
|
||||
# WHILE lendo arquivo linha-a-linha
|
||||
while IFS= read -r linha; do # IFS= preserva espacos, -r impede escape de \
|
||||
echo "Lida: $linha"
|
||||
done < arquivo.txt
|
||||
|
||||
# UNTIL (oposto do while: roda ate condicao ser verdadeira)
|
||||
n=0
|
||||
until [ $n -ge 3 ]; do
|
||||
echo "n=$n"
|
||||
((n++))
|
||||
done
|
||||
|
||||
# ---------- FUNCOES ----------
|
||||
|
||||
saudacao() { # Define a funcao
|
||||
local pessoa="$1" # local: variavel apenas dentro da funcao
|
||||
echo "Ola, $pessoa!"
|
||||
return 0 # Codigo de saida (opcional, 0 = sucesso)
|
||||
}
|
||||
|
||||
saudacao "Joao" # Chama a funcao com argumento
|
||||
|
||||
# Funcao que retorna valor via echo
|
||||
soma() {
|
||||
echo $(($1 + $2)) # Imprime o resultado
|
||||
}
|
||||
|
||||
resultado=$(soma 5 3) # Captura via command substitution
|
||||
echo "5+3=$resultado"
|
||||
|
||||
# ---------- ARRAYS ----------
|
||||
|
||||
frutas=("maca" "banana" "laranja") # Array indexado
|
||||
echo "${frutas[0]}" # Primeiro elemento
|
||||
echo "${frutas[@]}" # Todos os elementos
|
||||
echo "${#frutas[@]}" # Quantidade de elementos
|
||||
frutas+=("uva") # Adiciona ao final
|
||||
|
||||
for f in "${frutas[@]}"; do # Itera (aspas preservam espacos em elementos)
|
||||
echo "$f"
|
||||
done
|
||||
|
||||
# ---------- TRATAMENTO DE ERRO ----------
|
||||
|
||||
set -e # Aborta script no primeiro erro
|
||||
set -u # Aborta se usar variavel nao definida
|
||||
set -o pipefail # Detecta erros no MEIO de pipes
|
||||
set -euo pipefail # Combinacao recomendada para scripts robustos
|
||||
|
||||
# Verificacao manual:
|
||||
if ! comando; then # Se o comando falhou
|
||||
echo "Erro!" >&2 # >&2 escreve no stderr
|
||||
exit 1
|
||||
fi
|
||||
88
exemplos/linux/07_text_processing.sh
Executable file
88
exemplos/linux/07_text_processing.sh
Executable file
|
|
@ -0,0 +1,88 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 7: Processamento de texto (sort, uniq, cut, tr, sed, awk)
|
||||
# Ferramentas para transformar e analisar dados de texto.
|
||||
|
||||
# ---------- SORT (ordenacao) ----------
|
||||
|
||||
sort arquivo.txt # Ordena linhas alfabeticamente
|
||||
sort -r arquivo.txt # -r = reverso (decrescente)
|
||||
sort -n numeros.txt # -n = numerico (1, 2, 10 - nao 1, 10, 2)
|
||||
sort -u arquivo.txt # -u = unique (remove duplicatas durante a ordenacao)
|
||||
sort -k 2 dados.txt # Ordena pela 2a coluna
|
||||
sort -t: -k 3 -n /etc/passwd # Delimitador ":", ordena pela 3a coluna numerica
|
||||
sort -h tamanhos.txt # -h = human readable (1K, 2M, 3G)
|
||||
|
||||
# ---------- UNIQ (remover/contar duplicatas) ----------
|
||||
# IMPORTANTE: uniq so funciona em linhas ADJACENTES, por isso quase sempre vem apos sort
|
||||
|
||||
sort arquivo.txt | uniq # Remove duplicatas
|
||||
sort arquivo.txt | uniq -c # Conta ocorrencias de cada linha
|
||||
sort arquivo.txt | uniq -d # So mostra linhas DUPLICADAS
|
||||
sort arquivo.txt | uniq -u # So mostra linhas UNICAS (sem duplicata)
|
||||
|
||||
# Combo classico: top 10 palavras mais frequentes
|
||||
cat texto.txt | tr ' ' '\n' | sort | uniq -c | sort -rn | head -10
|
||||
|
||||
# ---------- CUT (extrair colunas) ----------
|
||||
|
||||
cut -d',' -f1 dados.csv # -d define delimitador, -f seleciona campo(s)
|
||||
cut -d',' -f1,3 dados.csv # Campos 1 e 3
|
||||
cut -d',' -f2-4 dados.csv # Faixa de campos (2 ate 4)
|
||||
cut -c1-10 arquivo.txt # -c por CARACTER (primeiros 10)
|
||||
cut -f1 dados.tsv # Default: delimitador e TAB
|
||||
|
||||
# ---------- TR (translate/transform) ----------
|
||||
|
||||
echo "hello" | tr 'a-z' 'A-Z' # Converte minusculas em MAIUSCULAS
|
||||
echo "HELLO" | tr 'A-Z' 'a-z' # MAIUSCULAS em minusculas
|
||||
echo "a,b,c" | tr ',' ' ' # Substitui virgula por espaco
|
||||
echo "aaabbbccc" | tr -s 'a' # -s "squeeze": colapsa repeticoes
|
||||
echo "hello123" | tr -d '0-9' # -d apaga: remove digitos
|
||||
echo "ola_mundo" | tr '_' '-' # ola-mundo
|
||||
|
||||
# ---------- SED (stream editor) ----------
|
||||
|
||||
sed 's/antigo/novo/' arquivo.txt # Substitui PRIMEIRA ocorrencia de cada linha
|
||||
sed 's/antigo/novo/g' arquivo.txt # /g = global, todas as ocorrencias
|
||||
sed -i 's/antigo/novo/g' arquivo.txt # -i = in-place (modifica o arquivo)
|
||||
sed -i.bak 's/antigo/novo/g' arquivo.txt # -i.bak cria backup .bak antes
|
||||
sed '5d' arquivo.txt # Apaga a linha 5
|
||||
sed '/padrao/d' arquivo.txt # Apaga linhas que casam com o padrao
|
||||
sed -n '10,20p' arquivo.txt # -n suprime, p imprime: so as linhas 10-20
|
||||
sed 's/^/PREFIXO: /' arquivo.txt # Adiciona prefixo em cada linha
|
||||
sed 's/$/ FIM/' arquivo.txt # Adiciona sufixo
|
||||
|
||||
# Multiplos comandos em sed:
|
||||
sed -e 's/a/A/g' -e 's/b/B/g' arquivo.txt
|
||||
|
||||
# ---------- AWK (linguagem de processamento de campos) ----------
|
||||
|
||||
awk '{print $1}' arquivo.txt # Imprime a 1a coluna (default: split por espaco)
|
||||
awk '{print $1, $3}' arquivo.txt # Colunas 1 e 3 (virgula no print = OFS)
|
||||
awk -F',' '{print $2}' dados.csv # -F define o delimitador
|
||||
awk 'NR==5' arquivo.txt # NR = numero da linha (so a 5a)
|
||||
awk 'NR>=10 && NR<=20' arquivo.txt # Linhas 10 a 20
|
||||
awk '/erro/' log.txt # Linhas que casam com "erro" (como grep)
|
||||
awk '/erro/ {print $1}' log.txt # Primeira coluna so de linhas com "erro"
|
||||
|
||||
# Soma de valores na 2a coluna:
|
||||
awk '{soma += $2} END {print soma}' dados.txt
|
||||
|
||||
# Media de valores na 1a coluna:
|
||||
awk '{soma += $1; n++} END {print soma/n}' numeros.txt
|
||||
|
||||
# Conta linhas (como wc -l):
|
||||
awk 'END {print NR}' arquivo.txt
|
||||
|
||||
# Aplicacao real: extrair IPs unicos do access log do Nginx
|
||||
awk '{print $1}' access.log | sort -u
|
||||
|
||||
# ---------- COMANDOS BONUS ----------
|
||||
|
||||
xargs # Constroi linhas de comando a partir do stdin
|
||||
seq 1 10 # Gera sequencia: 1 2 3 ... 10
|
||||
seq 1 2 10 # 1 3 5 7 9 (passo 2)
|
||||
shuf arquivo.txt # Embaralha as linhas aleatoriamente
|
||||
diff a.txt b.txt # Mostra diferencas entre dois arquivos
|
||||
comm a.txt b.txt # Compara dois arquivos ordenados (3 colunas)
|
||||
paste a.txt b.txt # Junta arquivos lado a lado (separado por TAB)
|
||||
103
exemplos/linux/08_networking.sh
Executable file
103
exemplos/linux/08_networking.sh
Executable file
|
|
@ -0,0 +1,103 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 8: Comandos de rede
|
||||
# Diagnostico, requisicoes HTTP, transferencia de arquivos, conectividade.
|
||||
|
||||
# ---------- INFORMACOES DE REDE ----------
|
||||
|
||||
ip addr # Mostra IPs das interfaces (substituto moderno do ifconfig)
|
||||
ip addr show eth0 # Detalhes da interface eth0
|
||||
ip route # Tabela de roteamento (rota padrao = gateway)
|
||||
ip link # Estado fisico das interfaces
|
||||
|
||||
hostname # Nome da maquina
|
||||
hostname -I # IPs da maquina (todas interfaces)
|
||||
|
||||
# ---------- CONECTIVIDADE ----------
|
||||
|
||||
ping google.com # Testa conectividade (Ctrl+C para parar)
|
||||
ping -c 4 google.com # -c 4 envia apenas 4 pacotes e para
|
||||
ping -W 2 google.com # -W 2 timeout de 2 segundos por pacote
|
||||
|
||||
traceroute google.com # Mostra cada salto ate o destino
|
||||
mtr google.com # Combina ping + traceroute em tempo real (excelente)
|
||||
|
||||
# ---------- DNS ----------
|
||||
|
||||
nslookup google.com # Resolve dominio para IP (tradicional)
|
||||
dig google.com # Mais detalhado e flexivel
|
||||
dig +short google.com # Apenas a resposta (so o IP)
|
||||
dig MX gmail.com # Consulta tipo especifico (MX = email)
|
||||
host google.com # Versao simples e rapida
|
||||
|
||||
cat /etc/hosts # Mapeamento manual de hostnames (verificado antes do DNS)
|
||||
cat /etc/resolv.conf # Servidores DNS configurados
|
||||
|
||||
# ---------- PORTAS E CONEXOES ----------
|
||||
|
||||
ss -tuln # Sockets em LISTEN; -t TCP -u UDP -l listen -n numerico
|
||||
ss -tunap # -a todos, -p mostra processo
|
||||
ss -tn state established # Apenas conexoes TCP estabelecidas
|
||||
|
||||
netstat -tuln # Antigo equivalente (ss e o moderno)
|
||||
|
||||
lsof -i :8080 # Quem esta usando a porta 8080?
|
||||
lsof -i tcp:80 # Conexoes TCP na porta 80
|
||||
fuser 8080/tcp # Outro jeito de ver quem usa uma porta
|
||||
|
||||
# ---------- CURL (cliente HTTP) ----------
|
||||
|
||||
curl https://api.exemplo.com # GET simples
|
||||
curl -i https://api.exemplo.com # -i inclui headers da resposta
|
||||
curl -I https://api.exemplo.com # -I (HEAD): apenas headers
|
||||
curl -L https://exemplo.com # -L segue redirecionamentos (301/302)
|
||||
curl -o pagina.html https://exemplo.com # -o salva em arquivo
|
||||
curl -O https://exemplo.com/arquivo.zip # -O usa o nome remoto
|
||||
curl -v https://api.exemplo.com # -v verbose (mostra request/response)
|
||||
curl -s https://api.exemplo.com # -s silent (sem barra de progresso)
|
||||
|
||||
# POST com JSON:
|
||||
curl -X POST https://api.exemplo.com/users \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer TOKEN" \
|
||||
-d '{"nome": "Alice", "email": "alice@ex.com"}'
|
||||
|
||||
# Upload de arquivo:
|
||||
curl -F "file=@imagem.jpg" https://api.exemplo.com/upload
|
||||
|
||||
# Com timeout:
|
||||
curl --max-time 10 https://api.exemplo.com # Aborta apos 10s
|
||||
|
||||
# ---------- WGET (downloads) ----------
|
||||
|
||||
wget https://exemplo.com/arquivo.zip # Baixa o arquivo
|
||||
wget -c https://exemplo.com/arquivo.zip # -c continua download interrompido
|
||||
wget -r -np https://exemplo.com/docs/ # -r recursivo, -np nao sobe diretorio
|
||||
wget --limit-rate=200k arquivo # Limita velocidade
|
||||
|
||||
# ---------- SSH ----------
|
||||
|
||||
ssh usuario@servidor.com # Conecta via SSH (porta 22 default)
|
||||
ssh -p 2222 usuario@servidor.com # Porta customizada
|
||||
ssh -i ~/.ssh/chave.pem usuario@servidor.com # Usa chave especifica
|
||||
ssh usuario@servidor "ls -la /var/log" # Executa comando remoto e sai
|
||||
|
||||
# Copiar arquivos via SSH:
|
||||
scp arquivo.txt usuario@servidor:/tmp/ # Local -> remoto
|
||||
scp usuario@servidor:/tmp/arquivo.txt . # Remoto -> local
|
||||
scp -r pasta/ usuario@servidor:/tmp/ # -r para diretorios
|
||||
|
||||
# Rsync (transferencia inteligente, so envia diferencas):
|
||||
rsync -avz pasta/ usuario@servidor:/destino/ # -a archive, -v verbose, -z compress
|
||||
rsync -avz --delete origem/ destino/ # --delete remove arquivos extras no destino
|
||||
|
||||
# Tunel SSH (encaminhamento de porta):
|
||||
ssh -L 8080:localhost:80 usuario@servidor # localhost:8080 -> servidor:80
|
||||
ssh -R 9090:localhost:3000 usuario@servidor # Reverso: servidor:9090 -> local:3000
|
||||
|
||||
# ---------- TESTES RAPIDOS ----------
|
||||
|
||||
# Verifica se uma porta esta aberta em outra maquina:
|
||||
nc -zv servidor.com 443 # nc = netcat; -z scan, -v verbose
|
||||
|
||||
# Servidor HTTP rapido para testes (Python):
|
||||
python3 -m http.server 8000 # Serve diretorio atual na porta 8000
|
||||
109
exemplos/linux/09_cron_servicos.sh
Executable file
109
exemplos/linux/09_cron_servicos.sh
Executable file
|
|
@ -0,0 +1,109 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 9: Tarefas agendadas (cron) e servicos (systemd)
|
||||
# Como automatizar execucao periodica e gerenciar daemons.
|
||||
|
||||
# ---------- CRON ----------
|
||||
|
||||
crontab -l # Lista as tarefas agendadas do usuario atual
|
||||
crontab -e # Edita as tarefas (abre editor padrao)
|
||||
crontab -r # REMOVE todas as tarefas (cuidado!)
|
||||
sudo crontab -l -u alice # Lista tarefas de outro usuario (precisa de root)
|
||||
|
||||
# Formato de uma linha do crontab:
|
||||
# m h dom mon dow comando
|
||||
# | | | | |
|
||||
# | | | | +----- dia da semana (0-7, 0 e 7 = domingo)
|
||||
# | | | +---------- mes (1-12)
|
||||
# | | +--------------- dia do mes (1-31)
|
||||
# | +------------------- hora (0-23)
|
||||
# +----------------------- minuto (0-59)
|
||||
#
|
||||
# Exemplos:
|
||||
# * * * * * comando -> a cada minuto
|
||||
# 0 * * * * comando -> no minuto 0 de cada hora
|
||||
# */5 * * * * comando -> a cada 5 minutos
|
||||
# 0 3 * * * /backup.sh -> todo dia as 03:00
|
||||
# 0 9 * * 1 comando -> toda segunda-feira as 09:00
|
||||
# 0 0 1 * * comando -> primeiro dia de cada mes a meia-noite
|
||||
# 30 22 * * 1-5 comando -> seg a sex as 22:30
|
||||
|
||||
# Atalhos especiais (mais legiveis):
|
||||
# @reboot -> ao iniciar a maquina
|
||||
# @hourly -> 0 * * * *
|
||||
# @daily -> 0 0 * * *
|
||||
# @weekly -> 0 0 * * 0
|
||||
# @monthly -> 0 0 1 * *
|
||||
# @yearly -> 0 0 1 1 *
|
||||
|
||||
# DICAS importantes ao usar cron:
|
||||
# 1. O ambiente do cron e MINIMO (PATH limitado). Use caminhos ABSOLUTOS:
|
||||
# BAD : python script.py
|
||||
# GOOD: /usr/bin/python3 /home/alice/script.py
|
||||
#
|
||||
# 2. Redirecione a saida para evitar emails do sistema:
|
||||
# 0 3 * * * /backup.sh > /var/log/backup.log 2>&1
|
||||
#
|
||||
# 3. Defina variaveis no topo do crontab quando necessario:
|
||||
# SHELL=/bin/bash
|
||||
# PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
# MAILTO=admin@exemplo.com
|
||||
|
||||
# Logs do cron:
|
||||
sudo tail -f /var/log/cron # CentOS/RHEL
|
||||
sudo tail -f /var/log/syslog | grep CRON # Debian/Ubuntu
|
||||
|
||||
# ---------- AT (execucao unica agendada) ----------
|
||||
|
||||
echo "comando" | at 14:30 # Executa as 14:30
|
||||
echo "/backup.sh" | at now + 2 hours # Em 2 horas
|
||||
echo "comando" | at "tomorrow 09:00" # Amanha as 9
|
||||
atq # Lista jobs do at
|
||||
atrm 3 # Remove o job 3
|
||||
|
||||
# ---------- SYSTEMD (gerenciamento de servicos) ----------
|
||||
|
||||
# Servicos sao definidos em arquivos .service em:
|
||||
# /etc/systemd/system/ -> customizados (manual)
|
||||
# /lib/systemd/system/ -> instalados via pacotes
|
||||
|
||||
sudo systemctl start nginx # Inicia o servico
|
||||
sudo systemctl stop nginx # Para
|
||||
sudo systemctl restart nginx # Reinicia (stop + start)
|
||||
sudo systemctl reload nginx # Recarrega config sem derrubar (se suportado)
|
||||
sudo systemctl status nginx # Mostra estado, PID, logs recentes
|
||||
sudo systemctl enable nginx # Habilita inicio automatico no boot
|
||||
sudo systemctl disable nginx # Desabilita inicio automatico
|
||||
sudo systemctl is-active nginx # Imprime "active" ou "inactive"
|
||||
sudo systemctl is-enabled nginx # Imprime "enabled" ou "disabled"
|
||||
sudo systemctl list-units --type=service # Lista todos os servicos
|
||||
sudo systemctl daemon-reload # Recarrega o systemd apos editar .service
|
||||
|
||||
# ---------- JOURNALCTL (logs do systemd) ----------
|
||||
|
||||
sudo journalctl # Todos os logs do sistema
|
||||
sudo journalctl -u nginx # Apenas do servico nginx
|
||||
sudo journalctl -u nginx -f # -f = follow (tail em tempo real)
|
||||
sudo journalctl -u nginx --since "1 hour ago" # Ultima hora
|
||||
sudo journalctl -u nginx --since today # Desde o inicio do dia
|
||||
sudo journalctl -p err # Apenas erros (priority)
|
||||
sudo journalctl -n 50 # Ultimas 50 linhas
|
||||
sudo journalctl --vacuum-time=7d # Apaga logs com mais de 7 dias
|
||||
|
||||
# ---------- EXEMPLO DE ARQUIVO .service ----------
|
||||
# Salvar em: /etc/systemd/system/minha-app.service
|
||||
#
|
||||
# [Unit]
|
||||
# Description=Minha Aplicacao Python
|
||||
# After=network.target # Inicia depois que a rede subir
|
||||
#
|
||||
# [Service]
|
||||
# Type=simple # Processo continuo (nao daemoniza)
|
||||
# User=appuser # Usuario que roda o servico
|
||||
# WorkingDirectory=/opt/minha-app
|
||||
# ExecStart=/usr/bin/python3 /opt/minha-app/app.py
|
||||
# Restart=always # Reinicia se cair
|
||||
# RestartSec=5 # Espera 5s antes de reiniciar
|
||||
# Environment="ENV=production" # Variavel de ambiente
|
||||
#
|
||||
# [Install]
|
||||
# WantedBy=multi-user.target # Em qual target inicia (multi-user = boot normal)
|
||||
107
exemplos/linux/10_script_pratico_backup.sh
Executable file
107
exemplos/linux/10_script_pratico_backup.sh
Executable file
|
|
@ -0,0 +1,107 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 10: Script pratico - backup automatizado
|
||||
# Junta varios conceitos: variaveis, funcoes, condicionais, logs, error handling.
|
||||
|
||||
# Modo estrito: aborta no primeiro erro, em variavel nao definida ou erro em pipe.
|
||||
set -euo pipefail
|
||||
|
||||
# ---------- CONFIGURACAO ----------
|
||||
|
||||
# Diretorio que sera copiado.
|
||||
ORIGEM="${1:-/home/alice/projetos}"
|
||||
|
||||
# Onde os backups serao guardados.
|
||||
DESTINO="/var/backups"
|
||||
|
||||
# Quantos dias de backup manter (mais antigos sao apagados).
|
||||
RETENCAO_DIAS=7
|
||||
|
||||
# Nome do arquivo: backup_2026-05-26_14-30-00.tar.gz
|
||||
DATA=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
NOME_ARQUIVO="backup_${DATA}.tar.gz"
|
||||
CAMINHO_BACKUP="${DESTINO}/${NOME_ARQUIVO}"
|
||||
|
||||
# Arquivo de log com a data de hoje.
|
||||
LOG_FILE="/var/log/backup_$(date +%Y-%m-%d).log"
|
||||
|
||||
# ---------- FUNCAO DE LOG ----------
|
||||
|
||||
# Escreve no log E na tela, sempre com timestamp.
|
||||
log() {
|
||||
local mensagem="$1"
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
# tee -a faz append no arquivo E imprime na tela.
|
||||
echo "[${timestamp}] ${mensagem}" | tee -a "${LOG_FILE}"
|
||||
}
|
||||
|
||||
# ---------- FUNCAO DE TRATAMENTO DE ERRO ----------
|
||||
|
||||
# Chamada automaticamente em caso de erro (via trap).
|
||||
tratar_erro() {
|
||||
local linha=$1
|
||||
log "ERRO na linha ${linha}. Abortando."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# trap registra um handler para sinais/eventos.
|
||||
# ERR dispara quando qualquer comando retorna codigo de erro.
|
||||
# $LINENO e a variavel especial com o numero da linha atual.
|
||||
trap 'tratar_erro $LINENO' ERR
|
||||
|
||||
# ---------- VALIDACOES ----------
|
||||
|
||||
# Verifica se o diretorio de origem existe.
|
||||
if [ ! -d "${ORIGEM}" ]; then
|
||||
log "ERRO: diretorio de origem '${ORIGEM}' nao existe."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Cria o destino se nao existir (-p evita erro se ja existir).
|
||||
mkdir -p "${DESTINO}"
|
||||
|
||||
# Verifica se temos permissao de escrita no destino.
|
||||
if [ ! -w "${DESTINO}" ]; then
|
||||
log "ERRO: sem permissao de escrita em '${DESTINO}'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ---------- EXECUCAO DO BACKUP ----------
|
||||
|
||||
log "Iniciando backup de '${ORIGEM}' para '${CAMINHO_BACKUP}'"
|
||||
|
||||
# Calcula o tamanho da origem antes (informativo).
|
||||
tamanho_origem=$(du -sh "${ORIGEM}" | cut -f1)
|
||||
log "Tamanho da origem: ${tamanho_origem}"
|
||||
|
||||
# Cria o arquivo tar comprimido.
|
||||
# c = create, z = gzip, f = arquivo de saida.
|
||||
# --exclude evita pastas que nao queremos no backup.
|
||||
tar czf "${CAMINHO_BACKUP}" \
|
||||
--exclude='node_modules' \
|
||||
--exclude='__pycache__' \
|
||||
--exclude='.venv' \
|
||||
--exclude='*.log' \
|
||||
-C "$(dirname "${ORIGEM}")" \
|
||||
"$(basename "${ORIGEM}")"
|
||||
|
||||
# Calcula o tamanho final do backup.
|
||||
tamanho_backup=$(du -sh "${CAMINHO_BACKUP}" | cut -f1)
|
||||
log "Backup criado: ${tamanho_backup}"
|
||||
|
||||
# ---------- LIMPEZA DE BACKUPS ANTIGOS ----------
|
||||
|
||||
log "Removendo backups com mais de ${RETENCAO_DIAS} dias..."
|
||||
|
||||
# Encontra arquivos backup_*.tar.gz antigos e os apaga.
|
||||
# -type f = apenas arquivos
|
||||
# -mtime +N = modificados ha mais de N dias
|
||||
# -print mostra o que foi deletado (para o log)
|
||||
removidos=$(find "${DESTINO}" -maxdepth 1 -type f -name 'backup_*.tar.gz' -mtime "+${RETENCAO_DIAS}" -print -delete | wc -l)
|
||||
|
||||
log "Arquivos antigos removidos: ${removidos}"
|
||||
|
||||
# ---------- FIM ----------
|
||||
|
||||
log "Backup concluido com sucesso!"
|
||||
exit 0
|
||||
93
exemplos/linux/11_disco_memoria.sh
Executable file
93
exemplos/linux/11_disco_memoria.sh
Executable file
|
|
@ -0,0 +1,93 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 11: Diagnostico de disco e memoria
|
||||
# Comandos para investigar uso de recursos e encontrar gargalos.
|
||||
|
||||
# ---------- USO DE DISCO ----------
|
||||
|
||||
df -h # Espaco usado/livre por particao (-h = human readable)
|
||||
df -i # Uso de INODES (cada arquivo consome um inode)
|
||||
df -h /var # Apenas a particao que contem /var
|
||||
|
||||
du -sh /var/log # Tamanho TOTAL do diretorio (-s sumario, -h legivel)
|
||||
du -sh /var/log/* # Tamanho de cada item dentro de /var/log
|
||||
du -h --max-depth=1 /var # Profundidade 1: mostra subdiretorios imediatos
|
||||
du -ah /var/log | sort -rh | head -20 # Top 20 maiores arquivos/pastas
|
||||
|
||||
# Diferenca importante:
|
||||
# df = espaco no FILESYSTEM (visao do disco)
|
||||
# du = soma dos arquivos VISIVEIS (visao do conteudo)
|
||||
# Discrepancia comum: arquivos deletados ainda abertos por processos.
|
||||
sudo lsof | grep deleted # Encontra arquivos deletados mas ainda em uso
|
||||
|
||||
# ---------- MEMORIA ----------
|
||||
|
||||
free -h # Memoria fisica e swap (formato legivel)
|
||||
free -m # Em megabytes
|
||||
free -s 2 # Atualiza a cada 2 segundos (Ctrl+C para sair)
|
||||
|
||||
# Saida tipica do "free -h":
|
||||
# total used free shared buff/cache available
|
||||
# Mem: 15Gi 4.2Gi 1.8Gi 300Mi 9.0Gi 10Gi
|
||||
# Swap: 2.0Gi 0B 2.0Gi
|
||||
#
|
||||
# CHAVE: "available" e o que importa - inclui buff/cache que pode ser liberado.
|
||||
# Linux usa RAM ociosa como cache. "free baixo" NAO significa pouca memoria!
|
||||
|
||||
cat /proc/meminfo # Detalhes brutos da memoria do kernel
|
||||
cat /proc/swaps # Areas de swap ativas
|
||||
|
||||
# ---------- IO E DESEMPENHO DO DISCO ----------
|
||||
|
||||
iostat # Estatisticas de IO (precisa do pacote sysstat)
|
||||
iostat -x 2 # Estendido, a cada 2 segundos
|
||||
iotop # Como o top, mas para IO (qual processo le/escreve mais)
|
||||
|
||||
# ---------- ENCONTRAR ARQUIVOS GRANDES ----------
|
||||
|
||||
# Top 10 maiores arquivos em /var:
|
||||
sudo find /var -type f -exec du -h {} + 2>/dev/null | sort -rh | head -10
|
||||
|
||||
# Arquivos maiores que 1 GB no sistema:
|
||||
sudo find / -type f -size +1G 2>/dev/null
|
||||
|
||||
# Arquivos modificados recentemente (uteis para investigar incidentes):
|
||||
sudo find /var/log -type f -mmin -60 # Logs modificados na ultima hora
|
||||
|
||||
# ---------- COMPRESSAO E DESCOMPRESSAO ----------
|
||||
|
||||
# tar (juntar muitos arquivos em um):
|
||||
tar cvf saida.tar pasta/ # c=create, v=verbose, f=arquivo
|
||||
tar czf saida.tar.gz pasta/ # z = comprime com gzip
|
||||
tar cjf saida.tar.bz2 pasta/ # j = comprime com bzip2 (melhor compressao)
|
||||
tar cJf saida.tar.xz pasta/ # J = comprime com xz (ainda melhor)
|
||||
|
||||
tar xvf arquivo.tar # x=extract
|
||||
tar xzf arquivo.tar.gz # Extrai .tar.gz
|
||||
tar xzf arquivo.tar.gz -C /tmp # -C extrai em diretorio especifico
|
||||
tar tzf arquivo.tar.gz # t=list (so lista o conteudo)
|
||||
|
||||
# gzip, bzip2, xz (compressao de arquivos individuais):
|
||||
gzip arquivo.txt # Comprime para arquivo.txt.gz (apaga original)
|
||||
gzip -k arquivo.txt # -k mantem o original
|
||||
gunzip arquivo.txt.gz # Descomprime
|
||||
zcat arquivo.txt.gz # Le sem descomprimir (otimo para logs)
|
||||
|
||||
# zip (compativel com Windows):
|
||||
zip -r arquivo.zip pasta/ # -r recursivo
|
||||
unzip arquivo.zip # Descomprime
|
||||
unzip -l arquivo.zip # -l so lista o conteudo
|
||||
|
||||
# ---------- INFORMACOES DO SISTEMA ----------
|
||||
|
||||
uname -a # Tudo (kernel, host, arch)
|
||||
uname -r # Apenas versao do kernel
|
||||
cat /etc/os-release # Distribuicao e versao
|
||||
lsb_release -a # Idem (precisa do lsb-release)
|
||||
cat /proc/cpuinfo | grep "model name" | head -1 # Modelo do CPU
|
||||
nproc # Numero de cores
|
||||
uptime # Tempo ligado + load average
|
||||
|
||||
# Load average (numero apos "load average:"):
|
||||
# - 3 numeros: ultimo 1min, 5min, 15min
|
||||
# - 1.0 em sistema 1-core = 100% de carga
|
||||
# - Em sistema com N cores, valor saudavel e < N
|
||||
113
exemplos/linux/12_variaveis_ambiente.sh
Executable file
113
exemplos/linux/12_variaveis_ambiente.sh
Executable file
|
|
@ -0,0 +1,113 @@
|
|||
#!/bin/bash
|
||||
# Exemplo 12: Variaveis de ambiente e configuracao do shell
|
||||
# Como o shell encontra programas, customizacao e persistencia.
|
||||
|
||||
# ---------- VARIAVEIS DE AMBIENTE COMUNS ----------
|
||||
|
||||
echo $HOME # Diretorio do usuario (ex: /home/alice)
|
||||
echo $USER # Nome do usuario
|
||||
echo $SHELL # Shell padrao (/bin/bash, /bin/zsh, etc)
|
||||
echo $PATH # Diretorios onde o shell busca executaveis
|
||||
echo $PWD # Diretorio atual (sinonimo de pwd)
|
||||
echo $LANG # Locale (ex: pt_BR.UTF-8)
|
||||
echo $TERM # Tipo de terminal (xterm, screen, etc)
|
||||
|
||||
env # Lista TODAS as variaveis de ambiente
|
||||
printenv USER # Imprime apenas a variavel especifica
|
||||
printenv | grep -i path # Filtra variaveis relacionadas a PATH
|
||||
|
||||
# ---------- CRIAR E EXPORTAR VARIAVEIS ----------
|
||||
|
||||
MINHA_VAR="ola" # Cria variavel LOCAL ao shell atual
|
||||
echo $MINHA_VAR # Funciona no mesmo shell
|
||||
|
||||
export MINHA_VAR="ola" # export torna disponivel para SUBPROCESSOS
|
||||
# Sem export, scripts e programas filhos NAO veem a variavel.
|
||||
|
||||
# Forma combinada:
|
||||
export MINHA_VAR="ola"
|
||||
|
||||
# Exportar varias de uma vez:
|
||||
export NAME="alice" AGE=30 ROLE="admin"
|
||||
|
||||
# Remover variavel:
|
||||
unset MINHA_VAR
|
||||
|
||||
# ---------- PATH (onde o shell procura executaveis) ----------
|
||||
|
||||
# Estrutura: caminhos separados por ":"
|
||||
# /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
|
||||
# Adicionar ao PATH temporariamente:
|
||||
export PATH="$PATH:/opt/meu_app/bin" # Adiciona no FINAL (menor prioridade)
|
||||
export PATH="/opt/meu_app/bin:$PATH" # Adiciona no INICIO (maior prioridade)
|
||||
|
||||
# Verificar onde um programa esta:
|
||||
which python3 # /usr/bin/python3
|
||||
type python3 # Mostra se e alias, builtin, funcao ou arquivo
|
||||
command -v python3 # Forma POSIX (preferida em scripts)
|
||||
|
||||
# ---------- ARQUIVOS DE CONFIGURACAO DO BASH ----------
|
||||
|
||||
# Ordem de carregamento:
|
||||
#
|
||||
# Login shell (ssh, console fisico):
|
||||
# 1. /etc/profile -> configuracao global do sistema
|
||||
# 2. ~/.bash_profile -> primeiro encontrado tem prioridade
|
||||
# OU ~/.bash_login
|
||||
# OU ~/.profile
|
||||
#
|
||||
# Shell interativo nao-login (abriu terminal dentro de sessao):
|
||||
# 1. /etc/bash.bashrc -> global
|
||||
# 2. ~/.bashrc -> do usuario
|
||||
#
|
||||
# Convencao MUITO comum: ~/.bash_profile chama ~/.bashrc para garantir que tudo carregue.
|
||||
# Por isso a maioria das customizacoes vai em ~/.bashrc.
|
||||
|
||||
# Apos editar, aplicar sem deslogar:
|
||||
source ~/.bashrc # source executa no shell ATUAL (vs subshell)
|
||||
. ~/.bashrc # . e o atalho de source
|
||||
|
||||
# ---------- EXEMPLO DE LINHAS COMUNS NO ~/.bashrc ----------
|
||||
|
||||
# # Adicionar diretorios ao PATH
|
||||
# export PATH="$HOME/.local/bin:$PATH"
|
||||
#
|
||||
# # Aliases para comandos frequentes
|
||||
# alias ll='ls -lah'
|
||||
# alias gs='git status'
|
||||
# alias gco='git checkout'
|
||||
# alias ..='cd ..'
|
||||
# alias ...='cd ../..'
|
||||
# alias serve='python3 -m http.server 8000'
|
||||
#
|
||||
# # Tornar prompt colorido com info de git (exemplo simplificado)
|
||||
# parse_git_branch() {
|
||||
# git branch 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
|
||||
# }
|
||||
# PS1='\u@\h:\w$(parse_git_branch)\$ '
|
||||
#
|
||||
# # Historico maior e sem duplicatas
|
||||
# HISTSIZE=10000
|
||||
# HISTFILESIZE=20000
|
||||
# HISTCONTROL=ignoredups:erasedups
|
||||
#
|
||||
# # Funcao customizada
|
||||
# mkcd() {
|
||||
# mkdir -p "$1" && cd "$1"
|
||||
# }
|
||||
|
||||
# ---------- USO EM SCRIPTS ----------
|
||||
|
||||
# Ler arquivo .env (formato KEY=VALUE) em um script:
|
||||
if [ -f .env ]; then
|
||||
set -a # Marca para EXPORTAR automaticamente
|
||||
source .env # Carrega o arquivo
|
||||
set +a # Desliga o auto-export
|
||||
fi
|
||||
|
||||
# Validar variavel obrigatoria:
|
||||
: "${API_KEY:?Variavel API_KEY nao definida}" # Aborta se API_KEY estiver vazia/nao-definida
|
||||
|
||||
# Valor default se nao definida:
|
||||
PORTA="${PORT:-8000}" # Usa $PORT, ou 8000 se nao definida
|
||||
49
exemplos/linux/README.md
Normal file
49
exemplos/linux/README.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Exemplos Linux / Bash
|
||||
|
||||
Colecao de exemplos comentados linha-a-linha em portugues, cobrindo os comandos e tecnicas mais cobrados em entrevistas SWE/DevOps.
|
||||
|
||||
## Indice
|
||||
|
||||
| # | Arquivo | Topico |
|
||||
|---|---------|--------|
|
||||
| 01 | `01_basico_arquivos.sh` | Listagem, navegacao, copia, movimentacao, visualizacao |
|
||||
| 02 | `02_permissoes.sh` | chmod, chown, umask, sudo |
|
||||
| 03 | `03_busca_find_grep.sh` | find (por nome/tipo/data) e grep (por conteudo) |
|
||||
| 04 | `04_pipes_redirecionamento.sh` | Pipes, `>`, `>>`, `2>&1`, tee, heredoc |
|
||||
| 05 | `05_processos.sh` | ps, top, kill, sinais, jobs, nohup |
|
||||
| 06 | `06_bash_scripting.sh` | Variaveis, if/case, loops, funcoes, arrays |
|
||||
| 07 | `07_text_processing.sh` | sort, uniq, cut, tr, sed, awk |
|
||||
| 08 | `08_networking.sh` | curl, ssh, scp, rsync, dig, ss, lsof |
|
||||
| 09 | `09_cron_servicos.sh` | crontab, at, systemctl, journalctl |
|
||||
| 10 | `10_script_pratico_backup.sh` | Script real que junta todos os conceitos |
|
||||
| 11 | `11_disco_memoria.sh` | df, du, free, tar, gzip |
|
||||
| 12 | `12_variaveis_ambiente.sh` | PATH, export, .bashrc, dotfiles |
|
||||
|
||||
## Como usar
|
||||
|
||||
Os arquivos contem comandos didaticos com comentarios. NAO sao para executar diretamente do inicio ao fim (alguns precisariam de sudo ou arquivos especificos). Use como referencia:
|
||||
|
||||
```bash
|
||||
# Leia
|
||||
less exemplos/linux/06_bash_scripting.sh
|
||||
|
||||
# Ou execute trechos especificos no terminal
|
||||
```
|
||||
|
||||
O unico que e um script completo executavel e o `10_script_pratico_backup.sh`:
|
||||
|
||||
```bash
|
||||
chmod +x exemplos/linux/10_script_pratico_backup.sh
|
||||
./exemplos/linux/10_script_pratico_backup.sh /caminho/da/origem
|
||||
```
|
||||
|
||||
## Comandos mais cobrados em entrevistas
|
||||
|
||||
- **Pipelines complexos**: `find ... | xargs ...`, `cat ... | sort | uniq -c | sort -rn`
|
||||
- **grep com regex**: contagem de erros em log, extracao de campos
|
||||
- **awk para somas/medias**: agregacao rapida de dados em coluna
|
||||
- **sed para edicao em massa**: refactor de texto em multiplos arquivos
|
||||
- **Permissoes octais**: explicar `755`, `644`, `chmod +x`
|
||||
- **Sinais (kill -9 vs kill -15)**: diferenca entre SIGTERM e SIGKILL
|
||||
- **systemctl/journalctl**: ciclo de vida de servicos e leitura de logs
|
||||
- **SSH e tuneis**: encaminhamento de porta, chaves
|
||||
27
exemplos/python/01_reverse_string.py
Normal file
27
exemplos/python/01_reverse_string.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Exercicio: Inverter uma string
|
||||
# Problema classico de entrevista que testa manipulacao de strings.
|
||||
|
||||
def reverter_string(texto): # Define a funcao que recebe uma string como parametro
|
||||
return texto[::-1] # Usa slicing do Python com passo -1 para inverter a string
|
||||
|
||||
def reverter_string_manual(texto): # Versao manual sem usar slicing, mostra dominio do algoritmo
|
||||
resultado = "" # Cria uma string vazia para acumular o resultado
|
||||
for caractere in texto: # Itera sobre cada caractere da string original
|
||||
resultado = caractere + resultado # Concatena cada caractere ANTES do resultado, invertendo a ordem
|
||||
return resultado # Retorna a string ja invertida
|
||||
|
||||
def reverter_string_dois_ponteiros(texto): # Versao com dois ponteiros, comum em entrevistas
|
||||
lista = list(texto) # Converte a string para lista porque strings sao imutaveis em Python
|
||||
esquerda = 0 # Ponteiro que comeca no inicio da lista
|
||||
direita = len(lista) - 1 # Ponteiro que comeca no final da lista
|
||||
while esquerda < direita: # Enquanto os ponteiros nao se cruzarem
|
||||
lista[esquerda], lista[direita] = lista[direita], lista[esquerda] # Troca os elementos das duas pontas
|
||||
esquerda += 1 # Avanca o ponteiro da esquerda
|
||||
direita -= 1 # Recua o ponteiro da direita
|
||||
return "".join(lista) # Junta a lista de caracteres de volta em uma string
|
||||
|
||||
if __name__ == "__main__": # Bloco que so executa quando o arquivo e rodado diretamente
|
||||
entrada = "interview" # Define uma string de teste
|
||||
print(reverter_string(entrada)) # Imprime "weivretni" usando slicing
|
||||
print(reverter_string_manual(entrada)) # Imprime "weivretni" usando concatenacao
|
||||
print(reverter_string_dois_ponteiros(entrada)) # Imprime "weivretni" usando dois ponteiros
|
||||
30
exemplos/python/02_palindrome.py
Normal file
30
exemplos/python/02_palindrome.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Exercicio: Verificar se uma string e um palindromo
|
||||
# Palindromo e uma palavra ou frase que se le igual de tras para frente (ex: "arara", "ovo").
|
||||
|
||||
def eh_palindromo(texto): # Define a funcao que recebe uma string e retorna True ou False
|
||||
texto = texto.lower() # Converte para minusculas para ignorar diferenca entre maiusculas e minusculas
|
||||
texto = "".join(c for c in texto if c.isalnum()) # Remove espacos e pontuacao mantendo apenas letras e numeros
|
||||
return texto == texto[::-1] # Compara a string com sua versao invertida, retorna True se forem iguais
|
||||
|
||||
def eh_palindromo_dois_ponteiros(texto): # Versao otimizada com dois ponteiros (O(n) tempo, O(1) espaco extra)
|
||||
texto = texto.lower() # Normaliza para minusculas
|
||||
esquerda = 0 # Ponteiro que comeca no inicio
|
||||
direita = len(texto) - 1 # Ponteiro que comeca no final
|
||||
while esquerda < direita: # Continua enquanto os ponteiros nao se cruzarem
|
||||
if not texto[esquerda].isalnum(): # Se o caractere da esquerda nao for alfanumerico
|
||||
esquerda += 1 # Avanca o ponteiro da esquerda e pula a iteracao
|
||||
continue # Volta para o inicio do loop
|
||||
if not texto[direita].isalnum(): # Se o caractere da direita nao for alfanumerico
|
||||
direita -= 1 # Recua o ponteiro da direita e pula a iteracao
|
||||
continue # Volta para o inicio do loop
|
||||
if texto[esquerda] != texto[direita]: # Se os caracteres comparados forem diferentes
|
||||
return False # Nao e palindromo, retorna False imediatamente
|
||||
esquerda += 1 # Avanca o ponteiro da esquerda
|
||||
direita -= 1 # Recua o ponteiro da direita
|
||||
return True # Se chegou aqui, todos os caracteres bateram, e palindromo
|
||||
|
||||
if __name__ == "__main__": # Executa apenas quando o arquivo e rodado diretamente
|
||||
print(eh_palindromo("arara")) # Imprime True
|
||||
print(eh_palindromo("Python")) # Imprime False
|
||||
print(eh_palindromo("A man, a plan, a canal: Panama")) # Imprime True (classico do LeetCode)
|
||||
print(eh_palindromo_dois_ponteiros("race a car")) # Imprime False
|
||||
30
exemplos/python/03_fibonacci.py
Normal file
30
exemplos/python/03_fibonacci.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Exercicio: Sequencia de Fibonacci
|
||||
# Cada numero e a soma dos dois anteriores: 0, 1, 1, 2, 3, 5, 8, 13, 21...
|
||||
|
||||
def fibonacci_recursivo(n): # Versao recursiva, simples mas ineficiente (O(2^n))
|
||||
if n <= 1: # Caso base: fib(0)=0 e fib(1)=1
|
||||
return n # Retorna o proprio n
|
||||
return fibonacci_recursivo(n - 1) + fibonacci_recursivo(n - 2) # Chamada recursiva somando os dois anteriores
|
||||
|
||||
def fibonacci_iterativo(n): # Versao iterativa, eficiente (O(n) tempo, O(1) espaco)
|
||||
if n <= 1: # Trata os casos base diretamente
|
||||
return n # Retorna 0 ou 1
|
||||
anterior, atual = 0, 1 # Inicializa as duas variaveis com os dois primeiros valores
|
||||
for _ in range(2, n + 1): # Itera de 2 ate n (inclusive)
|
||||
anterior, atual = atual, anterior + atual # Atualiza as variaveis simultaneamente usando tupla
|
||||
return atual # Retorna o n-esimo numero de Fibonacci
|
||||
|
||||
def fibonacci_memoizado(n, memo=None): # Versao com memoization, otima (O(n) tempo)
|
||||
if memo is None: # Se nao foi passado um dicionario de memoria
|
||||
memo = {} # Cria um dicionario vazio para cache
|
||||
if n in memo: # Se ja calculamos este valor antes
|
||||
return memo[n] # Retorna direto do cache, evitando recomputacao
|
||||
if n <= 1: # Caso base
|
||||
return n # Retorna o proprio n
|
||||
memo[n] = fibonacci_memoizado(n - 1, memo) + fibonacci_memoizado(n - 2, memo) # Calcula e armazena no cache
|
||||
return memo[n] # Retorna o valor calculado
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
print(fibonacci_recursivo(10)) # Imprime 55
|
||||
print(fibonacci_iterativo(10)) # Imprime 55
|
||||
print(fibonacci_memoizado(50)) # Imprime 12586269025 (rapido mesmo com n grande)
|
||||
24
exemplos/python/04_two_sum.py
Normal file
24
exemplos/python/04_two_sum.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Exercicio: Two Sum (problema #1 do LeetCode)
|
||||
# Dado um array de numeros e um alvo, retornar os indices de dois numeros que somem o alvo.
|
||||
|
||||
def two_sum_forca_bruta(numeros, alvo): # Solucao ingenua O(n^2)
|
||||
for i in range(len(numeros)): # Itera sobre cada elemento usando indice i
|
||||
for j in range(i + 1, len(numeros)): # Itera sobre os elementos seguintes usando indice j
|
||||
if numeros[i] + numeros[j] == alvo: # Verifica se a soma dos dois e igual ao alvo
|
||||
return [i, j] # Retorna os indices encontrados
|
||||
return [] # Retorna lista vazia se nenhum par satisfaz a condicao
|
||||
|
||||
def two_sum_hash(numeros, alvo): # Solucao otima O(n) tempo, O(n) espaco
|
||||
vistos = {} # Dicionario para mapear valor -> indice ja visto
|
||||
for i, numero in enumerate(numeros): # Itera com indice e valor ao mesmo tempo
|
||||
complemento = alvo - numero # Calcula qual valor falta para chegar no alvo
|
||||
if complemento in vistos: # Se o complemento ja foi visto antes
|
||||
return [vistos[complemento], i] # Retorna indice do complemento e indice atual
|
||||
vistos[numero] = i # Armazena o numero atual e seu indice no dicionario
|
||||
return [] # Retorna lista vazia se nao encontrou par
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
nums = [2, 7, 11, 15] # Array de exemplo
|
||||
print(two_sum_forca_bruta(nums, 9)) # Imprime [0, 1] pois 2+7=9
|
||||
print(two_sum_hash(nums, 9)) # Imprime [0, 1] pois 2+7=9
|
||||
print(two_sum_hash([3, 2, 4], 6)) # Imprime [1, 2] pois 2+4=6
|
||||
26
exemplos/python/05_fizzbuzz.py
Normal file
26
exemplos/python/05_fizzbuzz.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Exercicio: FizzBuzz (classico de entrevistas iniciais)
|
||||
# Para numeros de 1 a N: imprimir "Fizz" se divisivel por 3, "Buzz" se por 5, "FizzBuzz" se por ambos.
|
||||
|
||||
def fizzbuzz(n): # Funcao que retorna a lista de resultados ate n
|
||||
resultado = [] # Lista que vai acumular os valores
|
||||
for i in range(1, n + 1): # Itera de 1 ate n (inclusive)
|
||||
if i % 15 == 0: # Se divisivel por 3 e 5 ao mesmo tempo (15 = 3*5)
|
||||
resultado.append("FizzBuzz") # Adiciona "FizzBuzz" a lista
|
||||
elif i % 3 == 0: # Se divisivel apenas por 3
|
||||
resultado.append("Fizz") # Adiciona "Fizz"
|
||||
elif i % 5 == 0: # Se divisivel apenas por 5
|
||||
resultado.append("Buzz") # Adiciona "Buzz"
|
||||
else: # Se nao for divisivel por 3 nem por 5
|
||||
resultado.append(str(i)) # Adiciona o proprio numero como string
|
||||
return resultado # Retorna a lista completa
|
||||
|
||||
def fizzbuzz_pythonico(n): # Versao mais idiomatica usando concatenacao de strings
|
||||
return [ # Retorna uma list comprehension
|
||||
("Fizz" * (i % 3 == 0) + "Buzz" * (i % 5 == 0)) or str(i) # Concatena "Fizz" e "Buzz" condicionalmente, ou usa o numero
|
||||
for i in range(1, n + 1) # Para cada i de 1 a n
|
||||
]
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
for valor in fizzbuzz(15): # Itera sobre os 15 primeiros resultados
|
||||
print(valor) # Imprime cada valor em uma linha
|
||||
print(fizzbuzz_pythonico(15)) # Imprime a lista completa da versao pythonica
|
||||
28
exemplos/python/06_anagram.py
Normal file
28
exemplos/python/06_anagram.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Exercicio: Verificar se duas strings sao anagramas
|
||||
# Anagrama: mesmas letras em ordem diferente (ex: "amor" e "roma").
|
||||
|
||||
def sao_anagramas_ordenado(a, b): # Solucao simples usando ordenacao O(n log n)
|
||||
return sorted(a.lower()) == sorted(b.lower()) # Ordena as letras e compara, ignorando maiusculas
|
||||
|
||||
def sao_anagramas_contagem(a, b): # Solucao com contagem de frequencia O(n)
|
||||
if len(a) != len(b): # Otimizacao: se tem tamanhos diferentes, nao podem ser anagramas
|
||||
return False # Retorna False imediatamente
|
||||
contagem = {} # Dicionario para contar frequencia das letras
|
||||
for letra in a.lower(): # Itera sobre cada letra da primeira string
|
||||
contagem[letra] = contagem.get(letra, 0) + 1 # Incrementa o contador (cria com 0 se nao existir)
|
||||
for letra in b.lower(): # Itera sobre cada letra da segunda string
|
||||
if letra not in contagem: # Se a letra nao existe no dicionario
|
||||
return False # Nao sao anagramas
|
||||
contagem[letra] -= 1 # Decrementa o contador
|
||||
if contagem[letra] < 0: # Se o contador ficou negativo, ha mais ocorrencias em b do que em a
|
||||
return False # Nao sao anagramas
|
||||
return True # Se passou por tudo sem retornar False, sao anagramas
|
||||
|
||||
def sao_anagramas_counter(a, b): # Versao pythonica usando collections.Counter
|
||||
from collections import Counter # Importa o Counter do modulo collections
|
||||
return Counter(a.lower()) == Counter(b.lower()) # Compara os contadores de frequencia diretamente
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
print(sao_anagramas_ordenado("amor", "roma")) # Imprime True
|
||||
print(sao_anagramas_contagem("listen", "silent")) # Imprime True
|
||||
print(sao_anagramas_counter("hello", "world")) # Imprime False
|
||||
34
exemplos/python/07_binary_search.py
Normal file
34
exemplos/python/07_binary_search.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Exercicio: Busca Binaria
|
||||
# Encontrar um elemento em um array ORDENADO em O(log n) tempo.
|
||||
|
||||
def busca_binaria(lista, alvo): # Versao iterativa
|
||||
esquerda = 0 # Ponteiro do inicio do intervalo de busca
|
||||
direita = len(lista) - 1 # Ponteiro do fim do intervalo de busca
|
||||
while esquerda <= direita: # Continua enquanto houver intervalo valido para buscar
|
||||
meio = (esquerda + direita) // 2 # Calcula o indice do meio usando divisao inteira
|
||||
if lista[meio] == alvo: # Se o elemento do meio e o que buscamos
|
||||
return meio # Retorna o indice encontrado
|
||||
elif lista[meio] < alvo: # Se o meio e menor que o alvo, descartamos a metade esquerda
|
||||
esquerda = meio + 1 # Move o ponteiro esquerdo para depois do meio
|
||||
else: # Se o meio e maior que o alvo, descartamos a metade direita
|
||||
direita = meio - 1 # Move o ponteiro direito para antes do meio
|
||||
return -1 # Retorna -1 se o elemento nao foi encontrado
|
||||
|
||||
def busca_binaria_recursiva(lista, alvo, esquerda=0, direita=None): # Versao recursiva
|
||||
if direita is None: # Se nao foi passado limite direito
|
||||
direita = len(lista) - 1 # Inicializa com o ultimo indice
|
||||
if esquerda > direita: # Caso base: intervalo invalido
|
||||
return -1 # Elemento nao encontrado
|
||||
meio = (esquerda + direita) // 2 # Calcula o meio
|
||||
if lista[meio] == alvo: # Encontrou o elemento
|
||||
return meio # Retorna o indice
|
||||
elif lista[meio] < alvo: # Busca na metade direita
|
||||
return busca_binaria_recursiva(lista, alvo, meio + 1, direita) # Chamada recursiva ajustando esquerda
|
||||
else: # Busca na metade esquerda
|
||||
return busca_binaria_recursiva(lista, alvo, esquerda, meio - 1) # Chamada recursiva ajustando direita
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
arr = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] # Lista ORDENADA (requisito da busca binaria)
|
||||
print(busca_binaria(arr, 7)) # Imprime 3 (indice do numero 7)
|
||||
print(busca_binaria(arr, 4)) # Imprime -1 (4 nao esta na lista)
|
||||
print(busca_binaria_recursiva(arr, 19)) # Imprime 9 (ultimo indice)
|
||||
18
exemplos/python/08_bubble_sort.py
Normal file
18
exemplos/python/08_bubble_sort.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Exercicio: Bubble Sort (Ordenacao por Bolha)
|
||||
# Algoritmo simples O(n^2) - bom para explicar ordenacao em entrevistas iniciais.
|
||||
|
||||
def bubble_sort(lista): # Funcao que ordena uma lista in-place
|
||||
n = len(lista) # Armazena o tamanho da lista
|
||||
for i in range(n): # Faz n passagens pela lista
|
||||
trocou = False # Flag para detectar se houve troca nesta passagem (otimizacao)
|
||||
for j in range(0, n - i - 1): # Itera ate o final nao ordenado (os ultimos i ja estao ordenados)
|
||||
if lista[j] > lista[j + 1]: # Se o elemento atual e maior que o proximo
|
||||
lista[j], lista[j + 1] = lista[j + 1], lista[j] # Troca os dois elementos (swap)
|
||||
trocou = True # Marca que houve troca nesta passagem
|
||||
if not trocou: # Se nao houve nenhuma troca, a lista ja esta ordenada
|
||||
break # Sai do loop, otimizando o algoritmo
|
||||
return lista # Retorna a lista ordenada
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
arr = [64, 34, 25, 12, 22, 11, 90] # Lista desordenada de exemplo
|
||||
print(bubble_sort(arr)) # Imprime [11, 12, 22, 25, 34, 64, 90]
|
||||
35
exemplos/python/09_quick_sort.py
Normal file
35
exemplos/python/09_quick_sort.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Exercicio: Quick Sort (Ordenacao Rapida)
|
||||
# Algoritmo divide-e-conquista com complexidade media O(n log n).
|
||||
|
||||
def quick_sort(lista): # Versao simples e legivel (usa memoria extra)
|
||||
if len(lista) <= 1: # Caso base: lista de 0 ou 1 elemento ja esta ordenada
|
||||
return lista # Retorna a lista como esta
|
||||
pivo = lista[len(lista) // 2] # Escolhe o elemento do meio como pivo (estrategia simples)
|
||||
menores = [x for x in lista if x < pivo] # Lista dos elementos menores que o pivo
|
||||
iguais = [x for x in lista if x == pivo] # Lista dos elementos iguais ao pivo
|
||||
maiores = [x for x in lista if x > pivo] # Lista dos elementos maiores que o pivo
|
||||
return quick_sort(menores) + iguais + quick_sort(maiores) # Concatena recursivamente os tres pedacos
|
||||
|
||||
def quick_sort_inplace(lista, inicio=0, fim=None): # Versao in-place (otima em memoria)
|
||||
if fim is None: # Se nao foi passado o fim
|
||||
fim = len(lista) - 1 # Usa o ultimo indice
|
||||
if inicio < fim: # So ordena se houver pelo menos 2 elementos
|
||||
indice_pivo = particionar(lista, inicio, fim) # Particiona e obtem a posicao final do pivo
|
||||
quick_sort_inplace(lista, inicio, indice_pivo - 1) # Ordena recursivamente a parte esquerda
|
||||
quick_sort_inplace(lista, indice_pivo + 1, fim) # Ordena recursivamente a parte direita
|
||||
return lista # Retorna a lista ordenada in-place
|
||||
|
||||
def particionar(lista, inicio, fim): # Funcao auxiliar de particao (esquema Lomuto)
|
||||
pivo = lista[fim] # Escolhe o ultimo elemento como pivo
|
||||
i = inicio - 1 # Indice do menor elemento, comeca antes do inicio
|
||||
for j in range(inicio, fim): # Itera do inicio ate antes do pivo
|
||||
if lista[j] <= pivo: # Se o elemento atual e menor ou igual ao pivo
|
||||
i += 1 # Avanca o indice dos menores
|
||||
lista[i], lista[j] = lista[j], lista[i] # Troca para colocar o menor no inicio
|
||||
lista[i + 1], lista[fim] = lista[fim], lista[i + 1] # Coloca o pivo em sua posicao final
|
||||
return i + 1 # Retorna a posicao final do pivo
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
arr = [10, 7, 8, 9, 1, 5] # Lista desordenada
|
||||
print(quick_sort(arr)) # Imprime [1, 5, 7, 8, 9, 10]
|
||||
print(quick_sort_inplace([3, 6, 8, 10, 1, 2, 1])) # Imprime [1, 1, 2, 3, 6, 8, 10]
|
||||
28
exemplos/python/10_merge_sort.py
Normal file
28
exemplos/python/10_merge_sort.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Exercicio: Merge Sort (Ordenacao por Intercalacao)
|
||||
# Algoritmo divide-e-conquista estavel com complexidade O(n log n) garantida.
|
||||
|
||||
def merge_sort(lista): # Funcao principal recursiva
|
||||
if len(lista) <= 1: # Caso base: lista com 0 ou 1 elemento ja esta ordenada
|
||||
return lista # Retorna a lista sem modificacao
|
||||
meio = len(lista) // 2 # Calcula o ponto medio da lista
|
||||
esquerda = merge_sort(lista[:meio]) # Ordena recursivamente a metade esquerda
|
||||
direita = merge_sort(lista[meio:]) # Ordena recursivamente a metade direita
|
||||
return intercalar(esquerda, direita) # Intercala as duas metades ordenadas
|
||||
|
||||
def intercalar(esquerda, direita): # Funcao que une duas listas ordenadas em uma so
|
||||
resultado = [] # Lista que vai conter o resultado final ordenado
|
||||
i = j = 0 # Ponteiros para percorrer cada uma das listas
|
||||
while i < len(esquerda) and j < len(direita): # Enquanto houver elementos em ambas
|
||||
if esquerda[i] <= direita[j]: # Se o elemento da esquerda e menor ou igual
|
||||
resultado.append(esquerda[i]) # Adiciona ao resultado
|
||||
i += 1 # Avanca o ponteiro da esquerda
|
||||
else: # Se o elemento da direita e menor
|
||||
resultado.append(direita[j]) # Adiciona ao resultado
|
||||
j += 1 # Avanca o ponteiro da direita
|
||||
resultado.extend(esquerda[i:]) # Adiciona os elementos restantes da esquerda (se houver)
|
||||
resultado.extend(direita[j:]) # Adiciona os elementos restantes da direita (se houver)
|
||||
return resultado # Retorna a lista intercalada e ordenada
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
arr = [38, 27, 43, 3, 9, 82, 10] # Lista desordenada
|
||||
print(merge_sort(arr)) # Imprime [3, 9, 10, 27, 38, 43, 82]
|
||||
66
exemplos/python/11_linked_list.py
Normal file
66
exemplos/python/11_linked_list.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# Exercicio: Lista Encadeada (Linked List)
|
||||
# Estrutura de dados onde cada no aponta para o proximo. Muito comum em entrevistas.
|
||||
|
||||
class No: # Classe que representa um no da lista
|
||||
def __init__(self, valor): # Construtor do no
|
||||
self.valor = valor # Armazena o valor do no
|
||||
self.proximo = None # Ponteiro para o proximo no, inicialmente None
|
||||
|
||||
class ListaEncadeada: # Classe que gerencia a lista
|
||||
def __init__(self): # Construtor da lista
|
||||
self.cabeca = None # Inicialmente a cabeca (primeiro no) e None
|
||||
|
||||
def adicionar(self, valor): # Adiciona um valor no final da lista (O(n))
|
||||
novo = No(valor) # Cria o novo no com o valor fornecido
|
||||
if not self.cabeca: # Se a lista esta vazia
|
||||
self.cabeca = novo # O novo no se torna a cabeca
|
||||
return # Termina a funcao
|
||||
atual = self.cabeca # Comeca a percorrer a partir da cabeca
|
||||
while atual.proximo: # Avanca ate chegar no ultimo no
|
||||
atual = atual.proximo # Move para o proximo no
|
||||
atual.proximo = novo # Liga o ultimo no ao novo no
|
||||
|
||||
def adicionar_inicio(self, valor): # Adiciona um valor no inicio da lista (O(1))
|
||||
novo = No(valor) # Cria o novo no
|
||||
novo.proximo = self.cabeca # O proximo do novo no e a antiga cabeca
|
||||
self.cabeca = novo # Atualiza a cabeca para o novo no
|
||||
|
||||
def remover(self, valor): # Remove a primeira ocorrencia do valor
|
||||
if not self.cabeca: # Se a lista esta vazia
|
||||
return # Nao ha o que remover
|
||||
if self.cabeca.valor == valor: # Se o valor esta na cabeca
|
||||
self.cabeca = self.cabeca.proximo # Atualiza a cabeca para o proximo no
|
||||
return # Remocao concluida
|
||||
atual = self.cabeca # Percorre a partir da cabeca
|
||||
while atual.proximo and atual.proximo.valor != valor: # Procura o no anterior ao alvo
|
||||
atual = atual.proximo # Avanca
|
||||
if atual.proximo: # Se encontrou o no
|
||||
atual.proximo = atual.proximo.proximo # Pula o no alvo, removendo-o da lista
|
||||
|
||||
def reverter(self): # Inverte a lista in-place (pergunta classica de entrevista)
|
||||
anterior = None # Inicialmente nao ha no anterior
|
||||
atual = self.cabeca # Comeca pela cabeca
|
||||
while atual: # Enquanto houver nos
|
||||
proximo_temp = atual.proximo # Salva o proximo no antes de modificar
|
||||
atual.proximo = anterior # Inverte o ponteiro para o anterior
|
||||
anterior = atual # Move o anterior para o atual
|
||||
atual = proximo_temp # Avanca para o proximo (que foi salvo)
|
||||
self.cabeca = anterior # A nova cabeca e o ultimo no visitado
|
||||
|
||||
def imprimir(self): # Imprime a lista no formato 1 -> 2 -> 3
|
||||
valores = [] # Lista para acumular os valores como string
|
||||
atual = self.cabeca # Comeca pela cabeca
|
||||
while atual: # Percorre todos os nos
|
||||
valores.append(str(atual.valor)) # Adiciona o valor como string
|
||||
atual = atual.proximo # Avanca para o proximo no
|
||||
print(" -> ".join(valores)) # Junta os valores com setas e imprime
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
lista = ListaEncadeada() # Cria uma lista vazia
|
||||
for v in [1, 2, 3, 4, 5]: # Para cada valor de 1 a 5
|
||||
lista.adicionar(v) # Adiciona no final
|
||||
lista.imprimir() # Imprime: 1 -> 2 -> 3 -> 4 -> 5
|
||||
lista.reverter() # Inverte a lista
|
||||
lista.imprimir() # Imprime: 5 -> 4 -> 3 -> 2 -> 1
|
||||
lista.remover(3) # Remove o no com valor 3
|
||||
lista.imprimir() # Imprime: 5 -> 4 -> 2 -> 1
|
||||
35
exemplos/python/12_stack.py
Normal file
35
exemplos/python/12_stack.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Exercicio: Pilha (Stack) - estrutura LIFO (Last In, First Out)
|
||||
# Operacoes principais: push, pop, peek - todas em O(1).
|
||||
|
||||
class Pilha: # Classe que representa a pilha
|
||||
def __init__(self): # Construtor
|
||||
self.itens = [] # Lista interna que armazena os elementos
|
||||
|
||||
def push(self, item): # Empilha um elemento no topo
|
||||
self.itens.append(item) # Adiciona no final da lista (topo da pilha)
|
||||
|
||||
def pop(self): # Desempilha e retorna o elemento do topo
|
||||
if self.esta_vazia(): # Verifica se a pilha esta vazia
|
||||
raise IndexError("pop em pilha vazia") # Levanta erro se vazia
|
||||
return self.itens.pop() # Remove e retorna o ultimo elemento da lista
|
||||
|
||||
def peek(self): # Retorna o elemento do topo SEM remover
|
||||
if self.esta_vazia(): # Verifica se a pilha esta vazia
|
||||
raise IndexError("peek em pilha vazia") # Levanta erro se vazia
|
||||
return self.itens[-1] # Retorna o ultimo elemento sem remover
|
||||
|
||||
def esta_vazia(self): # Verifica se a pilha esta vazia
|
||||
return len(self.itens) == 0 # Retorna True se nao ha elementos
|
||||
|
||||
def tamanho(self): # Retorna a quantidade de elementos
|
||||
return len(self.itens) # Tamanho da lista interna
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
p = Pilha() # Cria uma pilha vazia
|
||||
p.push(1) # Empilha 1, pilha: [1]
|
||||
p.push(2) # Empilha 2, pilha: [1, 2]
|
||||
p.push(3) # Empilha 3, pilha: [1, 2, 3]
|
||||
print(p.peek()) # Imprime 3 (topo da pilha)
|
||||
print(p.pop()) # Imprime 3, pilha: [1, 2]
|
||||
print(p.pop()) # Imprime 2, pilha: [1]
|
||||
print(p.tamanho()) # Imprime 1
|
||||
37
exemplos/python/13_queue.py
Normal file
37
exemplos/python/13_queue.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Exercicio: Fila (Queue) - estrutura FIFO (First In, First Out)
|
||||
# Para insercao/remocao em O(1) usamos collections.deque (mais eficiente que list.pop(0)).
|
||||
|
||||
from collections import deque # Importa deque, fila de duas pontas otimizada
|
||||
|
||||
class Fila: # Classe que representa a fila
|
||||
def __init__(self): # Construtor
|
||||
self.itens = deque() # Estrutura interna baseada em deque
|
||||
|
||||
def enqueue(self, item): # Adiciona item no final da fila (enfileirar)
|
||||
self.itens.append(item) # Append e O(1) no deque
|
||||
|
||||
def dequeue(self): # Remove e retorna o item do inicio da fila (desenfileirar)
|
||||
if self.esta_vazia(): # Verifica se ha elementos
|
||||
raise IndexError("dequeue em fila vazia") # Levanta erro se vazia
|
||||
return self.itens.popleft() # popleft e O(1) no deque (diferente de list)
|
||||
|
||||
def front(self): # Retorna o primeiro item SEM remover
|
||||
if self.esta_vazia(): # Verifica se ha elementos
|
||||
raise IndexError("front em fila vazia") # Levanta erro
|
||||
return self.itens[0] # Retorna o primeiro elemento
|
||||
|
||||
def esta_vazia(self): # Verifica se a fila esta vazia
|
||||
return len(self.itens) == 0 # True se tamanho for zero
|
||||
|
||||
def tamanho(self): # Quantidade de elementos
|
||||
return len(self.itens) # Tamanho do deque
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
f = Fila() # Cria fila vazia
|
||||
f.enqueue("a") # Fila: ["a"]
|
||||
f.enqueue("b") # Fila: ["a", "b"]
|
||||
f.enqueue("c") # Fila: ["a", "b", "c"]
|
||||
print(f.front()) # Imprime "a" (primeiro a entrar)
|
||||
print(f.dequeue()) # Imprime "a", fila: ["b", "c"]
|
||||
print(f.dequeue()) # Imprime "b", fila: ["c"]
|
||||
print(f.tamanho()) # Imprime 1
|
||||
22
exemplos/python/14_factorial.py
Normal file
22
exemplos/python/14_factorial.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Exercicio: Fatorial
|
||||
# n! = n * (n-1) * (n-2) * ... * 1, sendo 0! = 1 por convencao.
|
||||
|
||||
def fatorial_recursivo(n): # Versao recursiva (elegante)
|
||||
if n < 0: # Fatorial nao e definido para negativos
|
||||
raise ValueError("Fatorial nao definido para numeros negativos") # Levanta erro
|
||||
if n <= 1: # Caso base: 0! = 1 e 1! = 1
|
||||
return 1 # Retorna 1
|
||||
return n * fatorial_recursivo(n - 1) # Multiplica n pelo fatorial de n-1
|
||||
|
||||
def fatorial_iterativo(n): # Versao iterativa (sem risco de stack overflow)
|
||||
if n < 0: # Validacao para negativos
|
||||
raise ValueError("Fatorial nao definido para numeros negativos") # Erro
|
||||
resultado = 1 # Inicializa o acumulador com 1
|
||||
for i in range(2, n + 1): # Multiplica de 2 ate n (1 e identidade, pode pular)
|
||||
resultado *= i # Acumula o produto
|
||||
return resultado # Retorna o fatorial calculado
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
print(fatorial_recursivo(5)) # Imprime 120 (5*4*3*2*1)
|
||||
print(fatorial_iterativo(10)) # Imprime 3628800
|
||||
print(fatorial_iterativo(0)) # Imprime 1 (caso base)
|
||||
30
exemplos/python/15_prime_check.py
Normal file
30
exemplos/python/15_prime_check.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Exercicio: Verificar se um numero e primo
|
||||
# Numero primo: maior que 1 e divisivel apenas por 1 e por ele mesmo.
|
||||
|
||||
def eh_primo(n): # Versao otimizada O(sqrt(n))
|
||||
if n < 2: # Numeros menores que 2 nao sao primos
|
||||
return False # Retorna False
|
||||
if n == 2: # 2 e o unico primo par
|
||||
return True # Retorna True
|
||||
if n % 2 == 0: # Se for par e maior que 2, nao e primo
|
||||
return False # Retorna False
|
||||
i = 3 # Comeca a testar divisores impares a partir de 3
|
||||
while i * i <= n: # Basta testar ate a raiz quadrada de n
|
||||
if n % i == 0: # Se i divide n exatamente
|
||||
return False # n nao e primo
|
||||
i += 2 # Avanca para o proximo impar (pula numeros pares)
|
||||
return True # Se nao encontrou divisor, e primo
|
||||
|
||||
def crivo_eratostenes(limite): # Encontra todos os primos ate o limite eficientemente
|
||||
eh_primo_arr = [True] * (limite + 1) # Inicializa todos como True (candidatos a primo)
|
||||
eh_primo_arr[0] = eh_primo_arr[1] = False # 0 e 1 nao sao primos
|
||||
for i in range(2, int(limite ** 0.5) + 1): # Itera ate a raiz do limite
|
||||
if eh_primo_arr[i]: # Se i ainda esta marcado como primo
|
||||
for j in range(i * i, limite + 1, i): # Marca todos os multiplos de i como nao-primos
|
||||
eh_primo_arr[j] = False # Comecando de i*i (otimizacao do crivo)
|
||||
return [i for i, primo in enumerate(eh_primo_arr) if primo] # Retorna a lista de primos encontrados
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
print(eh_primo(17)) # Imprime True
|
||||
print(eh_primo(18)) # Imprime False
|
||||
print(crivo_eratostenes(30)) # Imprime [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
|
||||
22
exemplos/python/16_valid_parentheses.py
Normal file
22
exemplos/python/16_valid_parentheses.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Exercicio: Parenteses Validos (LeetCode #20)
|
||||
# Dada uma string com (), [], {}, verificar se estao balanceados corretamente.
|
||||
|
||||
def parenteses_validos(s): # Funcao que retorna True se a string esta balanceada
|
||||
pilha = [] # Pilha para armazenar os caracteres de abertura esperados
|
||||
pares = {")": "(", "]": "[", "}": "{"} # Mapeia fechamento -> abertura correspondente
|
||||
for c in s: # Itera sobre cada caractere da string
|
||||
if c in "([{": # Se for um caractere de abertura
|
||||
pilha.append(c) # Empilha para ser fechado depois
|
||||
elif c in ")]}": # Se for um caractere de fechamento
|
||||
if not pilha: # Se a pilha esta vazia, fechamento sem abertura
|
||||
return False # Invalido
|
||||
if pilha.pop() != pares[c]: # Desempilha e verifica se bate com o esperado
|
||||
return False # Tipos nao batem, invalido
|
||||
return not pilha # No final, pilha deve estar vazia (todas aberturas foram fechadas)
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
print(parenteses_validos("()")) # Imprime True
|
||||
print(parenteses_validos("()[]{}")) # Imprime True
|
||||
print(parenteses_validos("(]")) # Imprime False
|
||||
print(parenteses_validos("([{}])")) # Imprime True
|
||||
print(parenteses_validos("((")) # Imprime False (abertura sem fechamento)
|
||||
22
exemplos/python/17_remove_duplicates.py
Normal file
22
exemplos/python/17_remove_duplicates.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Exercicio: Remover Duplicatas de uma Lista
|
||||
# Manter apenas a primeira ocorrencia de cada elemento, preservando a ordem.
|
||||
|
||||
def remover_duplicatas_set(lista): # Versao usando set (NAO preserva ordem em versoes antigas)
|
||||
return list(set(lista)) # Converte para set (remove duplicatas) e volta para lista
|
||||
|
||||
def remover_duplicatas_ordem(lista): # Versao que preserva a ordem de aparicao
|
||||
vistos = set() # Conjunto para registrar elementos ja vistos (lookup O(1))
|
||||
resultado = [] # Lista de saida ordenada
|
||||
for item in lista: # Itera sobre cada item
|
||||
if item not in vistos: # Se ainda nao foi visto
|
||||
vistos.add(item) # Marca como visto
|
||||
resultado.append(item) # Adiciona ao resultado
|
||||
return resultado # Retorna a lista sem duplicatas
|
||||
|
||||
def remover_duplicatas_dict(lista): # Versao pythonica usando dict.fromkeys (Python 3.7+)
|
||||
return list(dict.fromkeys(lista)) # dict preserva ordem de insercao e ignora chaves duplicadas
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
arr = [1, 2, 2, 3, 4, 4, 5, 1, 6] # Lista com duplicatas
|
||||
print(remover_duplicatas_ordem(arr)) # Imprime [1, 2, 3, 4, 5, 6]
|
||||
print(remover_duplicatas_dict(arr)) # Imprime [1, 2, 3, 4, 5, 6]
|
||||
26
exemplos/python/18_missing_number.py
Normal file
26
exemplos/python/18_missing_number.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Exercicio: Numero Faltante (LeetCode #268)
|
||||
# Dado um array com numeros de 0 a n, achar o unico numero faltante.
|
||||
|
||||
def numero_faltante_soma(numeros): # Solucao usando formula da soma O(n) tempo, O(1) espaco
|
||||
n = len(numeros) # Tamanho do array (que deveria conter 0..n)
|
||||
soma_esperada = n * (n + 1) // 2 # Formula de Gauss: soma de 0 a n
|
||||
soma_atual = sum(numeros) # Soma os numeros presentes no array
|
||||
return soma_esperada - soma_atual # Diferenca e o numero faltante
|
||||
|
||||
def numero_faltante_xor(numeros): # Solucao usando XOR (truque classico)
|
||||
resultado = len(numeros) # Inicializa com n (sera incluido no XOR)
|
||||
for i, num in enumerate(numeros): # Itera com indice e valor
|
||||
resultado ^= i ^ num # XOR de indices e valores cancela tudo, exceto o faltante
|
||||
return resultado # Retorna o numero que ficou apos os cancelamentos
|
||||
|
||||
def numero_faltante_set(numeros): # Solucao usando set, mais legivel
|
||||
conjunto = set(numeros) # Cria set para lookup O(1)
|
||||
for i in range(len(numeros) + 1): # Itera de 0 a n
|
||||
if i not in conjunto: # Se o numero nao esta no conjunto
|
||||
return i # E o faltante
|
||||
return -1 # Fallback (nao deveria acontecer)
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
print(numero_faltante_soma([3, 0, 1])) # Imprime 2
|
||||
print(numero_faltante_xor([9, 6, 4, 2, 3, 5, 7, 0, 1])) # Imprime 8
|
||||
print(numero_faltante_set([0, 1])) # Imprime 2
|
||||
36
exemplos/python/19_max_subarray.py
Normal file
36
exemplos/python/19_max_subarray.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Exercicio: Subarray de Soma Maxima (Algoritmo de Kadane) - LeetCode #53
|
||||
# Dado um array de inteiros (com positivos e negativos), achar o subarray contiguo de maior soma.
|
||||
|
||||
def max_subarray_kadane(numeros): # Algoritmo de Kadane: O(n) tempo, O(1) espaco
|
||||
if not numeros: # Caso de array vazio
|
||||
return 0 # Retorna 0 por convencao
|
||||
soma_atual = numeros[0] # Inicializa com o primeiro elemento
|
||||
soma_maxima = numeros[0] # Maior soma vista ate agora
|
||||
for num in numeros[1:]: # Itera a partir do segundo elemento
|
||||
soma_atual = max(num, soma_atual + num) # Recomeca em num ou estende a soma atual
|
||||
soma_maxima = max(soma_maxima, soma_atual) # Atualiza o maximo global
|
||||
return soma_maxima # Retorna a maior soma encontrada
|
||||
|
||||
def max_subarray_com_indices(numeros): # Variacao que tambem retorna os indices do subarray
|
||||
if not numeros: # Validacao
|
||||
return 0, -1, -1 # Retorno sentinela
|
||||
soma_atual = soma_maxima = numeros[0] # Inicializa ambas com o primeiro elemento
|
||||
inicio_atual = 0 # Indice de inicio do subarray atual
|
||||
inicio_max = 0 # Indice de inicio do melhor subarray ate agora
|
||||
fim_max = 0 # Indice de fim do melhor subarray ate agora
|
||||
for i in range(1, len(numeros)): # Itera do segundo ao ultimo
|
||||
if numeros[i] > soma_atual + numeros[i]: # Se for melhor recomecar do indice atual
|
||||
soma_atual = numeros[i] # Reinicia a soma com o numero atual
|
||||
inicio_atual = i # Atualiza o inicio do subarray
|
||||
else: # Caso contrario, estende o subarray atual
|
||||
soma_atual += numeros[i] # Soma o numero atual
|
||||
if soma_atual > soma_maxima: # Se encontramos uma soma maior
|
||||
soma_maxima = soma_atual # Atualiza a maxima
|
||||
inicio_max = inicio_atual # Atualiza o inicio do melhor
|
||||
fim_max = i # Atualiza o fim do melhor
|
||||
return soma_maxima, inicio_max, fim_max # Retorna soma e indices
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
arr = [-2, 1, -3, 4, -1, 2, 1, -5, 4] # Exemplo classico (soma maxima = 6 em [4,-1,2,1])
|
||||
print(max_subarray_kadane(arr)) # Imprime 6
|
||||
print(max_subarray_com_indices(arr)) # Imprime (6, 3, 6)
|
||||
20
exemplos/python/20_gcd.py
Normal file
20
exemplos/python/20_gcd.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Exercicio: Maximo Divisor Comum (MDC / GCD)
|
||||
# Algoritmo de Euclides - um dos algoritmos mais antigos da matematica.
|
||||
|
||||
def mdc_recursivo(a, b): # Versao recursiva (super elegante)
|
||||
if b == 0: # Caso base do algoritmo de Euclides
|
||||
return a # MDC e o proprio a quando b zera
|
||||
return mdc_recursivo(b, a % b) # Chamada recursiva com b e o resto de a/b
|
||||
|
||||
def mdc_iterativo(a, b): # Versao iterativa (sem risco de stack)
|
||||
while b: # Enquanto b nao for zero
|
||||
a, b = b, a % b # Atualiza a e b simultaneamente
|
||||
return a # Quando b vira 0, a contem o MDC
|
||||
|
||||
def mmc(a, b): # Minimo Multiplo Comum usando o MDC
|
||||
return abs(a * b) // mdc_iterativo(a, b) # Formula: mmc(a,b) = |a*b| / mdc(a,b)
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
print(mdc_recursivo(48, 18)) # Imprime 6
|
||||
print(mdc_iterativo(100, 75)) # Imprime 25
|
||||
print(mmc(4, 6)) # Imprime 12
|
||||
25
exemplos/python/21_count_chars.py
Normal file
25
exemplos/python/21_count_chars.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Exercicio: Contar a frequencia de caracteres em uma string
|
||||
# Pergunta comum para testar uso de dicionarios/hashmaps.
|
||||
|
||||
def contar_caracteres(texto): # Versao manual com dicionario
|
||||
contagem = {} # Dicionario para acumular as frequencias
|
||||
for c in texto: # Itera sobre cada caractere
|
||||
contagem[c] = contagem.get(c, 0) + 1 # Incrementa o contador (cria com 0 se nao existir)
|
||||
return contagem # Retorna o dicionario de frequencias
|
||||
|
||||
def contar_caracteres_counter(texto): # Versao pythonica com Counter
|
||||
from collections import Counter # Importa o Counter
|
||||
return dict(Counter(texto)) # Counter ja faz a contagem, convertemos para dict comum
|
||||
|
||||
def primeiro_caractere_unico(texto): # Variacao: achar o primeiro caractere nao repetido
|
||||
contagem = contar_caracteres(texto) # Conta as frequencias
|
||||
for i, c in enumerate(texto): # Itera mantendo a ordem original
|
||||
if contagem[c] == 1: # Se o caractere aparece apenas uma vez
|
||||
return i # Retorna o indice do primeiro unico
|
||||
return -1 # Retorna -1 se nenhum caractere e unico
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
print(contar_caracteres("banana")) # Imprime {'b': 1, 'a': 3, 'n': 2}
|
||||
print(contar_caracteres_counter("hello world")) # Imprime contagem das letras
|
||||
print(primeiro_caractere_unico("leetcode")) # Imprime 0 (l aparece apenas uma vez)
|
||||
print(primeiro_caractere_unico("loveleetcode")) # Imprime 2 (v e o primeiro unico)
|
||||
41
exemplos/python/22_reverse_linked_list.py
Normal file
41
exemplos/python/22_reverse_linked_list.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Exercicio: Inverter uma Lista Encadeada (LeetCode #206)
|
||||
# Pergunta de entrevista extremamente popular sobre manipulacao de ponteiros.
|
||||
|
||||
class No: # Definicao do no
|
||||
def __init__(self, valor, proximo=None): # Construtor recebe valor e proximo opcional
|
||||
self.valor = valor # Armazena o valor
|
||||
self.proximo = proximo # Aponta para o proximo no
|
||||
|
||||
def inverter_iterativo(cabeca): # Versao iterativa O(n) tempo, O(1) espaco
|
||||
anterior = None # No anterior comeca como None (sera o novo "fim")
|
||||
atual = cabeca # Comeca pelo no inicial
|
||||
while atual: # Enquanto houver nos para processar
|
||||
proximo_temp = atual.proximo # Salva referencia ao proximo antes de modificar
|
||||
atual.proximo = anterior # Inverte o ponteiro do no atual
|
||||
anterior = atual # Anterior avanca para o no atual
|
||||
atual = proximo_temp # Atual avanca para o proximo (salvo antes)
|
||||
return anterior # Anterior agora aponta para a nova cabeca
|
||||
|
||||
def inverter_recursivo(cabeca): # Versao recursiva O(n) tempo, O(n) espaco (pilha de chamadas)
|
||||
if not cabeca or not cabeca.proximo: # Caso base: lista vazia ou unico no
|
||||
return cabeca # Retorna o proprio no
|
||||
nova_cabeca = inverter_recursivo(cabeca.proximo) # Inverte recursivamente o restante
|
||||
cabeca.proximo.proximo = cabeca # O proximo no (ainda nao invertido) aponta para o atual
|
||||
cabeca.proximo = None # Desconecta o atual (sera o novo fim eventualmente)
|
||||
return nova_cabeca # Retorna a nova cabeca (ultimo no original)
|
||||
|
||||
def imprimir(cabeca): # Funcao auxiliar para visualizar a lista
|
||||
valores = [] # Lista de strings
|
||||
atual = cabeca # Percorre a partir da cabeca
|
||||
while atual: # Enquanto houver nos
|
||||
valores.append(str(atual.valor)) # Adiciona valor como string
|
||||
atual = atual.proximo # Avanca
|
||||
print(" -> ".join(valores)) # Imprime no formato 1 -> 2 -> 3
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
cabeca = No(1, No(2, No(3, No(4, No(5))))) # Cria lista 1 -> 2 -> 3 -> 4 -> 5
|
||||
imprimir(cabeca) # Imprime original
|
||||
invertida = inverter_iterativo(cabeca) # Inverte iterativamente
|
||||
imprimir(invertida) # Imprime 5 -> 4 -> 3 -> 2 -> 1
|
||||
de_novo = inverter_recursivo(invertida) # Inverte de novo (volta ao original)
|
||||
imprimir(de_novo) # Imprime 1 -> 2 -> 3 -> 4 -> 5
|
||||
73
exemplos/python/23_binary_tree.py
Normal file
73
exemplos/python/23_binary_tree.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# Exercicio: Arvore Binaria e Travessias (preorder, inorder, postorder, BFS)
|
||||
# Estrutura fundamental para entrevistas em empresas de tecnologia.
|
||||
|
||||
from collections import deque # Para a fila usada no BFS
|
||||
|
||||
class No: # Definicao do no da arvore
|
||||
def __init__(self, valor): # Construtor
|
||||
self.valor = valor # Armazena o valor do no
|
||||
self.esquerda = None # Referencia para o filho esquerdo
|
||||
self.direita = None # Referencia para o filho direito
|
||||
|
||||
def preorder(no, resultado=None): # Travessia pre-ordem: raiz, esquerda, direita
|
||||
if resultado is None: # Inicializa lista na primeira chamada
|
||||
resultado = [] # Cria lista vazia
|
||||
if no: # Se o no existe
|
||||
resultado.append(no.valor) # Visita a raiz primeiro
|
||||
preorder(no.esquerda, resultado) # Recurre na subarvore esquerda
|
||||
preorder(no.direita, resultado) # Recurre na subarvore direita
|
||||
return resultado # Retorna a lista de valores visitados
|
||||
|
||||
def inorder(no, resultado=None): # Travessia em-ordem: esquerda, raiz, direita (BST retorna ordenado)
|
||||
if resultado is None: # Inicializa lista
|
||||
resultado = [] # Lista vazia
|
||||
if no: # Se o no existe
|
||||
inorder(no.esquerda, resultado) # Visita a subarvore esquerda
|
||||
resultado.append(no.valor) # Visita a raiz no meio
|
||||
inorder(no.direita, resultado) # Visita a subarvore direita
|
||||
return resultado # Retorna a lista
|
||||
|
||||
def postorder(no, resultado=None): # Travessia pos-ordem: esquerda, direita, raiz
|
||||
if resultado is None: # Inicializa lista
|
||||
resultado = [] # Lista vazia
|
||||
if no: # Se o no existe
|
||||
postorder(no.esquerda, resultado) # Esquerda primeiro
|
||||
postorder(no.direita, resultado) # Depois direita
|
||||
resultado.append(no.valor) # Raiz por ultimo
|
||||
return resultado # Retorna a lista
|
||||
|
||||
def bfs(raiz): # Travessia em largura (Breadth-First Search) usando fila
|
||||
if not raiz: # Caso de arvore vazia
|
||||
return [] # Retorna lista vazia
|
||||
resultado = [] # Lista de valores visitados em ordem
|
||||
fila = deque([raiz]) # Fila contendo inicialmente a raiz
|
||||
while fila: # Enquanto houver nos a visitar
|
||||
no = fila.popleft() # Desenfileira o primeiro no
|
||||
resultado.append(no.valor) # Visita o no
|
||||
if no.esquerda: # Se tem filho esquerdo
|
||||
fila.append(no.esquerda) # Enfileira o filho esquerdo
|
||||
if no.direita: # Se tem filho direito
|
||||
fila.append(no.direita) # Enfileira o filho direito
|
||||
return resultado # Retorna os valores em ordem de nivel
|
||||
|
||||
def altura(no): # Calcula a altura (profundidade maxima) da arvore
|
||||
if not no: # Caso base: no nulo tem altura 0
|
||||
return 0 # Retorna 0
|
||||
return 1 + max(altura(no.esquerda), altura(no.direita)) # 1 + maior altura entre as subarvores
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
# Constroi a arvore: 1
|
||||
# / \
|
||||
# 2 3
|
||||
# / \
|
||||
# 4 5
|
||||
raiz = No(1) # Cria a raiz
|
||||
raiz.esquerda = No(2) # Filho esquerdo
|
||||
raiz.direita = No(3) # Filho direito
|
||||
raiz.esquerda.esquerda = No(4) # Neto esquerdo
|
||||
raiz.esquerda.direita = No(5) # Neto direito
|
||||
print("Preorder: ", preorder(raiz)) # [1, 2, 4, 5, 3]
|
||||
print("Inorder: ", inorder(raiz)) # [4, 2, 5, 1, 3]
|
||||
print("Postorder:", postorder(raiz)) # [4, 5, 2, 3, 1]
|
||||
print("BFS: ", bfs(raiz)) # [1, 2, 3, 4, 5]
|
||||
print("Altura: ", altura(raiz)) # 3
|
||||
31
exemplos/python/24_climbing_stairs.py
Normal file
31
exemplos/python/24_climbing_stairs.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Exercicio: Subindo Escadas (LeetCode #70)
|
||||
# De quantas formas distintas voce pode subir n degraus dando passos de 1 ou 2 por vez?
|
||||
# Resposta: e a sequencia de Fibonacci!
|
||||
|
||||
def subir_escadas_recursivo(n): # Versao recursiva ingenua O(2^n)
|
||||
if n <= 2: # Caso base: 1 degrau -> 1 forma, 2 degraus -> 2 formas
|
||||
return n # Retorna n
|
||||
return subir_escadas_recursivo(n - 1) + subir_escadas_recursivo(n - 2) # Soma os dois sub-problemas
|
||||
|
||||
def subir_escadas_dp(n): # Versao com programacao dinamica O(n) tempo, O(n) espaco
|
||||
if n <= 2: # Casos base
|
||||
return n # Retorna n
|
||||
dp = [0] * (n + 1) # Array para armazenar resultados intermediarios
|
||||
dp[1] = 1 # 1 degrau -> 1 forma
|
||||
dp[2] = 2 # 2 degraus -> 2 formas (1+1 ou 2)
|
||||
for i in range(3, n + 1): # Preenche de baixo para cima
|
||||
dp[i] = dp[i - 1] + dp[i - 2] # Combina os dois sub-problemas
|
||||
return dp[n] # Retorna a resposta para n degraus
|
||||
|
||||
def subir_escadas_otimo(n): # Versao otima O(n) tempo, O(1) espaco
|
||||
if n <= 2: # Casos base
|
||||
return n # Retorna n
|
||||
anterior, atual = 1, 2 # Variaveis que armazenam apenas os dois ultimos valores
|
||||
for _ in range(3, n + 1): # Avanca ate n
|
||||
anterior, atual = atual, anterior + atual # Atualiza simultaneamente
|
||||
return atual # Retorna o valor final
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
print(subir_escadas_recursivo(5)) # Imprime 8
|
||||
print(subir_escadas_dp(10)) # Imprime 89
|
||||
print(subir_escadas_otimo(45)) # Imprime 1836311903 (rapido)
|
||||
19
exemplos/python/25_best_time_stock.py
Normal file
19
exemplos/python/25_best_time_stock.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Exercicio: Melhor Momento para Comprar e Vender Acoes (LeetCode #121)
|
||||
# Dado precos diarios de uma acao, achar o lucro maximo possivel com 1 compra e 1 venda.
|
||||
|
||||
def lucro_maximo(precos): # Solucao otima O(n) tempo, O(1) espaco
|
||||
if not precos: # Lista vazia
|
||||
return 0 # Sem lucro possivel
|
||||
menor_preco = precos[0] # Rastreia o menor preco visto ate agora (melhor dia para comprar)
|
||||
lucro_max = 0 # Lucro maximo encontrado ate agora
|
||||
for preco in precos[1:]: # Itera a partir do segundo dia
|
||||
if preco < menor_preco: # Se achamos um preco menor (melhor compra)
|
||||
menor_preco = preco # Atualiza o menor preco
|
||||
else: # Caso contrario, podemos vender
|
||||
lucro_max = max(lucro_max, preco - menor_preco) # Atualiza o lucro maximo se for melhor
|
||||
return lucro_max # Retorna o melhor lucro possivel
|
||||
|
||||
if __name__ == "__main__": # Bloco de teste
|
||||
print(lucro_maximo([7, 1, 5, 3, 6, 4])) # Imprime 5 (compra a 1, vende a 6)
|
||||
print(lucro_maximo([7, 6, 4, 3, 1])) # Imprime 0 (precos so caem, melhor nao operar)
|
||||
print(lucro_maximo([2, 4, 1, 7])) # Imprime 6 (compra a 1, vende a 7)
|
||||
41
exemplos/python/README.md
Normal file
41
exemplos/python/README.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Exercicios Python para Entrevistas SWE
|
||||
|
||||
Colecao de exercicios resolvidos comumente solicitados em entrevistas tecnicas de Software Engineering em Python. Cada arquivo tem comentarios linha-a-linha em portugues explicando o que cada parte do codigo faz.
|
||||
|
||||
## Indice
|
||||
|
||||
| # | Arquivo | Topico |
|
||||
|---|---------|--------|
|
||||
| 01 | `01_reverse_string.py` | Inverter string (slicing, manual, dois ponteiros) |
|
||||
| 02 | `02_palindrome.py` | Verificar palindromo |
|
||||
| 03 | `03_fibonacci.py` | Fibonacci (recursivo, iterativo, memoizado) |
|
||||
| 04 | `04_two_sum.py` | Two Sum (forca bruta e hashmap) |
|
||||
| 05 | `05_fizzbuzz.py` | FizzBuzz |
|
||||
| 06 | `06_anagram.py` | Verificar anagramas |
|
||||
| 07 | `07_binary_search.py` | Busca binaria (iterativa e recursiva) |
|
||||
| 08 | `08_bubble_sort.py` | Bubble Sort |
|
||||
| 09 | `09_quick_sort.py` | Quick Sort |
|
||||
| 10 | `10_merge_sort.py` | Merge Sort |
|
||||
| 11 | `11_linked_list.py` | Lista encadeada (add, remove, reverter) |
|
||||
| 12 | `12_stack.py` | Pilha (Stack) |
|
||||
| 13 | `13_queue.py` | Fila (Queue) |
|
||||
| 14 | `14_factorial.py` | Fatorial |
|
||||
| 15 | `15_prime_check.py` | Numeros primos + Crivo de Eratostenes |
|
||||
| 16 | `16_valid_parentheses.py` | Parenteses balanceados |
|
||||
| 17 | `17_remove_duplicates.py` | Remover duplicatas |
|
||||
| 18 | `18_missing_number.py` | Numero faltante (soma, XOR, set) |
|
||||
| 19 | `19_max_subarray.py` | Subarray de soma maxima (Kadane) |
|
||||
| 20 | `20_gcd.py` | MDC e MMC (Euclides) |
|
||||
| 21 | `21_count_chars.py` | Contagem de caracteres |
|
||||
| 22 | `22_reverse_linked_list.py` | Inverter lista encadeada |
|
||||
| 23 | `23_binary_tree.py` | Arvore binaria + travessias (DFS/BFS) |
|
||||
| 24 | `24_climbing_stairs.py` | Subindo escadas (programacao dinamica) |
|
||||
| 25 | `25_best_time_stock.py` | Comprar/vender acoes |
|
||||
|
||||
## Como executar
|
||||
|
||||
```bash
|
||||
python3 exemplos/python/01_reverse_string.py
|
||||
```
|
||||
|
||||
Cada arquivo tem um bloco `if __name__ == "__main__":` com testes que demonstram o uso das funcoes.
|
||||
Loading…
Add table
Add a link
Reference in a new issue