Diário
Estas são as entradas do meu diário, onde compartilho pensamentos, ideias e reflexões do dia a dia. Você pode encontrar uma variedade de tópicos, desde experiências pessoais até observações sobre o mundo ao meu redor. Sinta-se à vontade para explorar e acompanhar minhas jornadas digitais.
Para gerar o diário, eu criei o aplicativo jnl que é um gerador de diário pessoal. E exportei as entradas marcadas com a tag public
para o site.
Redirecionando a saída do terminal.
Você pode redirecionar toda a saída de um script
para um arquivo usando um único comando no início do script
.
Nesse exemplo, a saída do comando ls
será direcionada para o arquivo out.txt
.
#!/bin/bash
exec >out.txt 2>&1
ls -al --color
Você também pode redirecionar a saída para o console, usando /dev/console
, requer permissão de root
.
#!/bin/bash
exec >/dev/console 2>&1
ls -al --color
O parâmetro --color
é usado para manter a saída colorida, porque o comando ls
detecta se a saída é um terminal ou não, e ajusta a saída de acordo.
Baytimetro
Esse fim de semana fiz algumas brincadeiras com o terminal, desenhando direto e recriei um recurso lá dos anos 80 que, apesar de extremamente simples, é muito útil: o baytimetro.
echo "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
echo " 1 2 3 4 5 6 7 8"
Ótimo chamar com seu desenho de tela e descobrir se você precisa colocar algum caractere mais para a direita ou esquerda.
É ridiculamente simples, mas fazer esse tipo de coisa tem um apelo nostálgico muito grande para mim.
Função toclip
Esta é uma função Bash que uso como parte de meus scripts e ambientes de desenvolvimento. Ela copia o conteúdo do stdin para a área de transferência. Muito útil quando você está acessando um servidor via SSH.
toclip() {
[[ ${SSH_CONNECTION-}${SSH_TTY-} ]] && {
printf $'\033]52;c;%s\a' "$(base64 -w0 2>/dev/null || base64 | tr -d '\n')"
return
}
case $OSTYPE in
darwin*) pbcopy ;;
linux*)
#command -v wl-copy >/dev/null 2>&1 && wl-copy && return
command -v xclip >/dev/null 2>&1 && xclip -selection clipboard && return
# Fallback Linux without xclip or wl-copy returns to OSC52
printf $'\033]52;c;%s\a' "$(base64 -w0 2>/dev/null || base64 | tr -d '\n')"
;;
esac
}
Exemplo de uso
Direto do stdin:
echo "Texto para copiar" | toclip
Copiando o conteúdo de um arquivo:
toclip < arquivo.txt
Listando servidores DNS
Para listar os servidores DNS usados no macOS:
scutil --dns
Útil para saber quais servidores foram pegos depois de renovar o DHCP.
Não largue o osso
Uma vez, meu tio William me contou uma história de um piloto de corrida que estava com ele e ia passar por uma curva com uma leve subida. Enquanto tangenciava a curva perfeitamente, em um único e contínuo movimento, reduziu a marcha e acelerou, ao mesmo tempo, virou a fita no toca-fitas. Sem trancos, com o carro ganhando somente a potência necessária. Fez tudo isso como se não fosse nada, enquanto conversava.
Meu tio usou essa história para me falar sobre preparo e sobre conhecer bem sua profissão. Essa habilidade não vem do nada, não é inata; vem de trabalho duro e determinação.
Para quem está lendo isso hoje, várias décadas depois, é difícil explicar a complexidade dessa manobra, naquele tempo de câmbios manuais e carburadores mecânicos. Principalmente se você não souber operar um toca-fitas.
Sinto falta dessas conversas com ele. Gostaria de ter assistido a mais corridas ao seu lado.
Nas palavras do Sr. William: – Não largue o osso.
n8n com padman
Tenho uma máquina que só tem uma regra: tudo que for executado nela deve ser feito em um container
.
# podman volume create n8n_data 2>/dev/null || true
podman run -it --rm \
--name n8n \
-p 5678:5678 \
-v n8n_data:/home/node/.n8n \
-e N8N_RUNNERS_ENABLED=true \
-e N8N_SECURE_COOKIE=false \
-e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \
docker.n8n.io/n8nio/n8n
Ajustes para rodar o n8n na rede interna
Essas configurações são para rede interna, maquina não acessível pela internet, sem SSL. Use apenas em ambiente de desenvolvimento ou teste.
Diminui as permissões do arquivo de configuração do n8n.
chmod 600 /home/user/.n8n/config
Rodando na rede interna sem SSL e com task runners habilitados:
export N8N_RUNNERS_ENABLED=true #enable task runners
export N8N_SECURE_COOKIE=false #disable secure cookies
npx n8n
Listar variáveis
Tecnica para fazer “debug de pobre” em Lua, listando variáveis globais e locais.
-- List all global variables
for name, value in pairs(_G) do
local repr = tostring(value)
print(string.format("%s = %s", name, repr))
end
-- List all local variables in the current function
-- This will only work if the code is run in a function context
local function list_locals()
local i = 1
while true do
local var_name, var_value = debug.getlocal(2, i)
if not var_name then break end
print(string.format("%s = %s", var_name, tostring(var_value)))
i = i + 1
end
end
-- Example
local function demo()
local a = 10
local b = "hello"
list_locals() -- This will list local variables a and b
end
demo()
Conway’s Game of Life
Essa noite de brincadeira, criei uma versão para terminal do consagrado Jogo da Vida de Conway (Conway’s Game of Life).
Sobre tentar manter um diário: Se eu não escrever o que tenho na cabeça imediatamente, provavelmente eu nunca vou escrever.
Processamento de Registros em Lote com PostgreSQL e Go
Este é um padrão interessante para processamento de registros em lote no Go com PostgreSQL. Ele utiliza transações e bloqueios para garantir que os registros sejam processados de forma segura e eficiente, evitando conflito entre múltiplas instâncias do processo.
O truque é combinar o uso de FOR UPDATE SKIP LOCKED
para evitar que múltiplas instâncias do processo leiam e processem o mesmo registro ao mesmo tempo, e o uso do índice (id) para evitar que algum erro de processamento faça com que o registro seja processado novamente porque não houve uma mudança de status.
Se houver um erro durante o processamento, o registro não é atualizado e permanece com o status ‘pendente’. Sem o WHERE id > $1
, o loop poderia entrar em um ciclo infinito tentando processar o mesmo registro repetidamente.
var id int
for {
done := func() bool {
const sqlStatement = `SELECT
id, ...
FROM ...
WHERE id > $1
AND status = 'pendente'
AND ...
ORDER BY id
FOR UPDATE SKIP LOCKED LIMIT 1;`
// aqui inicia uma transação
tx := ...
defer func() {
// mecanismo de rollback
}()
// então executa a consulta
err := tx.QueryRow(sqlStatement, id).Scan(&id, ...)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return true // não há mais registros
}
// trata outros erros
...
return false
}
// aqui faz o processamento do registro e atualiza o status
// pode ser fail, paid, processed, etc.
// ...
// se tudo estiver ok, confirma a transação
err = tx.Commit()
if err != nil {
// trata erro de commit geralmente log.Fatal(...)
}
return false // indica que o loop deve continuar
}()
if done {
break // não há mais registros para processar
}
}
Este é um exemplo bom para processamento de registros em lote e pode ser tranquilamente colocado para rodar de tempos em tempos, como um cron job, para processar registros pendentes em um banco de dados PostgreSQL.
Uma vantagem interessante é que, se o processamento demorar muito, automaticamente o cron vai carregar outras instâncias do processo, que vão pegar os registros que ainda não foram processados e não estão bloqueados (SKIP LOCKED). Isso permite que o sistema escale horizontalmente, processando mais registros em paralelo sem risco de conflitos.