Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Processos Unix & Ruby

Processos Unix & Ruby

Techtalk apresentando na Tagview sobre como conceitos de processos Unix e como manipula-los em Ruby.

Avatar for Rodrigo Navarro

Rodrigo Navarro

August 17, 2012

More Decks by Rodrigo Navarro

Other Decks in Programming

Transcript

  1. Recapitulando... Todo código é executando dentro de um processo •

    Process.pid • Process.ppid • $PROGRAM_NAME / $0 • ARGV é um array • ENV é repassado de pai para filho
  2. File Descriptors Todos os recursos em unix são tratados como

    arquivos: Arquivos são arquivos Sockets são arquivos Pipes são arquivos Devices (keyboard, monitor) são arquivos
  3. File Descriptors IO.fileno => Retorna o número do descritor password

    = File.open("/etc/passwd") password.fileno # 3 hosts = File.open("/etc/hosts") hosts.fileno # 4 password.close # nao é mais um file descriptor null = File.open("/dev/null") null.fileno # 3
  4. Standard Streams STDIN => Abstrai o input STDOUT => Abstrai

    o output STDERR => Abstrai a saída de erro def puts(*a) $stdout.puts(*a) nil end
  5. Códigos de Saída Quando um processo é encerrado, ele fornece

    um código numérico de saída, esse código vai de 0-255, e denota se o processo teve um erro ou não. Por convenção, o status de saída 0 significa que o processo foi com sucesso. at_exit { puts "Saindo..." } at_exit { puts "tchau!" } exit
  6. Fork • O processo que chamou o fork(2) é o

    pai e o novo processo criado é o filho. • O filho herda uma copia de toda a memoria usada pelo pai e todo os file descriptors • O filho ganha um PID próprio, ja que ele é um novo processo. Obviamente o PPID dele é do seu processo pai que chamou o fork (2) • O filho vai herdar uma copia dos file descriptors que foram criados pelo pai ate até o ponto do fork apenas.
  7. Fork if fork # Processo pai else # Processo filho

    end # Processo pai fork do # Processo filho end # Processo pai
  8. Process.wait fork do 5.times do sleep 1 puts "Eu sou

    um filho!" end end status = Process.wait abort "Adeus vida cruel..." favorite = fork do exit 10 end other = fork do exit 1 end pid, status = Process.waitpid2 favorite puts status.exitstatus
  9. Process.wait • Process wait é uma chamada bloqueante que faz

    o processo esperar um processo filho terminar para continuar • Retorna o PID do processo filho • Process.wait2 retorna o pid e o status • Se passar um parametro para o wait, espera um filho com PID específico, mas nesse caso é melhor usar Process.waitpid • Voce pode passar -1 para o wait e pro waitpid pra esperar qualquer processo
  10. Processos Zumbis™ Quando um processo não chama wait(2) em um

    filho. child_pid = fork { abort "morri..." } puts child_pid sleep ps -ho pid,state <child_pid> Irá mostrar Z (zombie)
  11. Processos Zumbis™ Use Process.detach caso você queira forkar- e-esquecer um

    processo. Não é a mesma coisa que um daemon. child_pid = fork { sleep 5 } Process.detach child_pid https://github. com/rubinius/rubinius/blob/master/kernel/comm on/process19.rb#L313
  12. Sinais - Default Actions • Term - termina o processo

    imediatamente • Core - termina o processo imediatamente e printa o stacktrace • Ign - ignora o sinal • Stop - para o processo (pause) • Cont - resume o processo
  13. Sinais SIGHUP 1 Term Hangup do terminal SIGINT 2 Term

    Interrupcao do keyboaard ctrl+c SIGQUIT 3 Core Quit do keyboard ctrl+\ SIGILL 4 Core Instrucao ilegal SIGABRT 6 Core Sinal Abort do abort(3) SIGFPE 8 Core Flotint point exception SIGKILL 9 Term Kill... SIGSEGV 11 Core Referencia invalida para memoria SIGPIPE 13 Term Broken pipe SIGALRM 14 Term Sinal do timer do alarm(2) SIGTERM 15 Term Sinal de termination SIGUSR1 30,10,16 Term User-defined signal 1 SIGUSR2 31,12,17 Term User-defined signal 2 (unicorn usa eles) SIGCHLD 20,17,18 Ign Filho terminou SIGCONT 19,18,25 Cont Continuar se parado
  14. Sinais - Alterando a default action puts Process.pid trap(:INT) {

    print "Nananinanao" } puts Process.pid trap(:INT, "IGNORE") SIGKILL e SIGSTOP não podem ser trapeados, nem bloqueados e nem ignorados
  15. Pipes Pipe permite um fluxo unidirecional de dados. Um dos

    lados escreve e o outro lado lê. reader, writer = IO.pipe writer.write("Oh hai!") writer.close puts reader.read
  16. Compartilhando pipes Como pipe é um file descriptor, eles são

    copiados quando é feito um fork. reader, writer = IO.pipe fork do 10.times do writer.puts "Another one bites the dust" end end while message = reader.gets puts message end
  17. Streams • Como um "arquivo infinito" • É necessário ter

    algum tipo de delimitador • HTTP utiliza vários \n\n para separar headers e body por exemplo • puts e gets usam o protocolo "\n"
  18. Unix Sockets • Sockets que só podem se comunicar na

    mesma maquina física • Permitem se comunicar por mensagens require 'socket' s1, s2 = Socket.pair(:UNIX, :DGRAM, 0) s1, s2 = UNIXSocket.pair # Sintaxe alternativa
  19. Preforking servers 1. Eficiência no uso de memória 2. Load

    balancing automático 3. Fácil administração • Unicorn • Apache pre-fork
  20. Daemons - Ruby 1.8 https://github.com/rack/rack/blob/master/lib/rack/server.rb#L307-319 if RUBY_VERSION < "1.9" exit

    if fork Process.setsid exit if fork Dir.chdir "/" STDIN.reopen "/dev/null" STDOUT.reopen "/dev/null", "a" STDERR.reopen "/dev/null", "a" else Process.daemon end
  21. exit if fork Isso faz uso do retorno nulo do

    processo que foi forkado. Logo, o pai morre nesse momento.
  22. Process.setsid 1. O processo vira um líder de sessão de

    uma nova sessão 2. O processo vira um líder de um grupo de processos 3. O processo não tem nenhum terminal de controle
  23. exit if fork exit if fork Process.setsid exit if fork

    Dir.chdir "/" STDIN.reopen "/dev/null" STDOUT.reopen "/dev/null", "a" STDERR.reopen "/dev/null", "a"
  24. Bonus - Como Resque usa o fork para gerenciar memória

    if @child = fork procline "Forked #{@child} at #{Time.now.to_i}" Process.wait(@child) else procline "Processing #{job.queue} since #{Time.now.to_i}" perform(job, &block) exit! unless @cant_fork end