php e seus demônios

63
PHP e seus demônios CRIANDO DAEMONS EM PHP

Upload: henrique-moody

Post on 08-Jul-2015

2.026 views

Category:

Technology


0 download

DESCRIPTION

Criando Daemons em PHP Macro tópicos • Forks • Sinais • Daemons • Spawn • Zombies • IPC

TRANSCRIPT

Page 1: PHP e seus demônios

PHP e seus demôniosCRIANDO  DAEMONS  EM  PHP

Page 2: PHP e seus demônios

PALESTRANTE

�2

Page 3: PHP e seus demônios

Henrique  Moody

• Desenvolvedor  web  com  foco  em  PHP  desde  2007  

• Usuário  assíduo  de  Linux  desde  2008  • Zend  Certified  Engineer  5.3  desde  2011  • Contribui  com  vários  projetos  Open  Source    • Líder  Técnico  • Desenvolvedor  PHP  Senior

�3

Page 4: PHP e seus demônios

PALESTRA

�4

Page 5: PHP e seus demônios

PHP  e  seus  demônios

• Forks  • Sinais  • Daemons  • Spawn  • Zombies  • IPC

�5

Page 6: PHP e seus demônios

FORKS

�6

Page 7: PHP e seus demônios

• Em  sistemas  operacionais  Unix-­‐like  fork  é  uma  operação  em  que  um  processo  cria  uma  cópia  de  si  mesmo  

• Fork  é  uma  forma  de  um  processo  executar  outro  ou  outros  processos  a  partir  de  si  mesmo  

• Quando  a  cópia  do  processo  é  criada  essa  cópia  é  chamada  de  processo  filho  tornando  o  processo  original  o  processo  pai  

• No  PHP  é  necessária  a  extensão  PCNTL  habilitada  e  extremamente  recomendável  a  extensão  POSIX  também  habilitada

�7

Page 8: PHP e seus demônios

PCNTL  (Process  Control)

• Deve  ser  habilitada  no  momento  da  compilação  do  PHP  (——enable-pcntl)  

• Suportada  apenas  para  sistemas  Unix-­‐like  • Não  funciona  em  web  servers  • Cria  e  gerencia  processos  e  sinais

�8

Page 9: PHP e seus demônios

POSIX  (Portable  Operating  System  Interface)

• Habilitada  por  padrão  na  compilação  do  PHP  • Suportada  apenas  para  sistemas  Unix-­‐like  • Fornece  uma  API  padrão  para  desenvolvimento  em  sistemas  Unix-­‐like  

• Gerencia  processos,  sessões,  grupos,  usuários  e  arquivos  de  sistemas  Unix-­‐like

�9

Page 10: PHP e seus demônios

Funcionamento

• A  função  pcntl_fork()  criará  o  fork  e  retornará  um  valor  diferente  para  cada  processo  (pai  e  filho)  

• Caso  pcntl_fork()  retorne  -1  ocorreu  um  erro  no  fork  • Caso  pcntl_fork()  retorne  0  houve  sucesso  no  fork.  O  processo  atual  é  o  filho  

• Caso  pcntl_fork()  retorne  um  número  maior  do  que  0  houve  sucesso  no  fork.  O  processo  atual  é  o  pai  e  o  retorno  de  pcntl_fork()  é  o  PID  do  filho  

• Nada  impede  um  processo  filho  criar  forks  de  si  mesmo  • Todas  as  variáveis  inicializadas  no  processo  pai  estarão  disponíveis  para  os  filhos

�10

Page 11: PHP e seus demônios

Forks/pcntl.php<?php$pid = pcntl_fork();if ($pid == -1) { // Falha na criação do fork echo 'Falha na criação do fork' . PHP_EOL;!} elseif ($pid > 0) { // Sou o processo pai echo 'Fork criado com sucesso sob o PID ' . $pid . PHP_EOL;!} else { // Sou o processo filho, em background mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet');}

�11

Page 12: PHP e seus demônios

Forks/pcntl+posix.php<?php$pid = pcntl_fork();if ($pid == -1) { // Falha na criação do fork echo 'Falha na criação do fork' . PHP_EOL;!} elseif ($pid > 0) { // Sou o processo pai echo 'Fork criado com sucesso sob o PID ' . $pid . PHP_EOL;!} else { // Sou o processo filho, em background if (0 !== posix_getuid()) { error_log('É necessário ser root para alterar informações do processo'); exit(2); }! if (! posix_setuid(1000)) { error_log('Não foi possível definir o usuário do processo como 1000'); exit(3); }! if (! posix_setgid(1000)) { error_log('Não foi possível definir o grupo do processo como 1000'); exit(4); }! mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet');}

�12

Page 13: PHP e seus demônios

SINAIS

�13

Page 14: PHP e seus demônios

• Em  sistemas  Unix-­‐like,  um  sinal  é  uma  notificação  de  software  a  um  processo  da  ocorrência  de  um  evento  

• Um  sinal  é  gerado  pelo  SO  quando  o  evento  que  causa  o  sinal  acontece  

• Existem  vários  sinais  que  podem  ser  enviados  para  um  processo,  alguns  deles  podem  ser  manipulados  pela  aplicação  já  outros  apenas  pelo  próprio  SO  

• Podemos  enviar  através  da  função  posix_kill()  • Podemos  definir  um  callback  para  manipular  sinais  através  da  função  pcntl_signal()

�14

Page 15: PHP e seus demônios

Lista  de  constantes  de  sinais  do  PHP• SIGABRT• SIGALRM• SIGBABY• SIGBUS• SIGCHLD• SIGCONT• SIGFPE• SIGHUP• SIGILL• SIGINT• SIGIO

• SIGIOT• SIGKILL• SIGPIPE• SIGPROF• SIGQUIT• SIGSEGV• SIGSTOP• SIGSYS• SIGTERM• SIGTRAP• SIGTSTP

• SIGTTIN• SIGTTOU• SIGURG• SIGUSR1• SIGUSR2• SIGVTALRM• SIGWINCH• SIGXCPU• SIGXFSZ

�15

Page 16: PHP e seus demônios

Mais  comuns• SIGHUP:  enviado  quando  o  sessão  (terminal)  do  processo  é  fechada  

• Pode  ser  interceptado  • SIGINT:  enviado  quando  um  se  pretende  interromper  o  processo  

• Pode  ser  interceptado  • Pode  ser  enviado  via  teclado,  com  Control-C,  e  em  alguns  sistemas  com  delete  ou  break  

• SIGTSTP:  enviado  quando  se  pretende  pausar  o  processo  • Pode  ser  interceptado  • Pode  ser  enviado  via  teclado,  com  Control-Z

• SIGCONT:  enviado  quando  se  pretende  despausar  o  processo  após  SIGTSTP  • Pode  ser  interceptado  

• SIGTERM:  enviado  quando  se  pretende  terminar  o  processo  (amigavelmente).  • Pode  ser  interceptado  

• SIGQUIT:  enviado  quando  se  pretende  encerrar  o  processo  e  obter  um  dump  de  memória.  • Pode  ser  interceptado  • Pode  ser  enviado  via  teclado,  com  Control-\  

• SIGKILL:  enviado  quando  se  pretende  encerrar  imediatamente  o  processo  • Não  ser  interceptado

�16

Page 17: PHP e seus demônios

Sinais/envio.php<?php!// Envia um 0 (verifica se o PID é válido ou não)posix_kill($pid, 0);!// Envia um SIGUSR1 (User-defined signal 1)posix_kill($pid, SIGUSR1);!// Envia um SIGSTOP (pausa a execução do processo)posix_kill($pid, SIGSTOP);!// Envia um SIGCONT (continua a execução do processo)posix_kill($pid, SIGCONT);!// Envia um SIGKILL (mata instantâneamente o processo)posix_kill($pid, SIGKILL);

�17

Page 18: PHP e seus demônios

Sinais/manipulacao.php<?php!declare(ticks = 1);function signalHandler($signal){ switch ($signal) { case SIGQUIT; error_log('Me fecharam com o teclado (Control-\)'); exit(1); case SIGINT: error_log('Me interromperam com o teclado (Control-C)'); exit(1); case SIGHUP: error_log('Fecharam meu terminal'); exit(1); case SIGTERM: error_log('Me pediram para me matar'); exit(0); }} !pcntl_signal(SIGQUIT, 'signalHandler');pcntl_signal(SIGINT, 'signalHandler');pcntl_signal(SIGHUP, 'signalHandler');pcntl_signal(SIGTERM, 'signalHandler');pcntl_signal(SIGTSTP, 'signalHandler');pcntl_signal(SIGTSTP, SIG_IGN); // SIG_IGN faz com que SIGTSTP seja ignoradopcntl_signal(SIGCONT, SIG_IGN); // SIG_IGN faz com que SIGCONT seja ignorado!echo 'PID: ' . getmypid() . PHP_EOL;while (true) { echo date('Y-m-d H:i:s') . PHP_EOL; sleep(1);}

�18

Page 19: PHP e seus demônios

DAEMONS

�19

Page 20: PHP e seus demônios

• Acrônimo  de  Disk  And  Execution  MONitor  (Monitor  de  Execução  e  de  Disco)  

• Em  Unix  e  outros  sistemas  operacionais  multi-­‐tarefas  é  um  programa  de  computador  que  roda  de  forma  independente  em  background,  ao  invés  de  ser  controlado  diretamente  por  um  usuário  

• Em  um  ambiente  Unix,  o  processo  pai  de  um  daemon  é  normalmente  (mas  nem  sempre)  o  processo  init  (PID=1)  

• Alguns  exemplos  de  daemons  são:  MySQL  Server,  Apache  Server,  Nginx  Server,  Cron  

• Muitas  vezes,  um  programa  se  torna  um  daemon  através  de  forking

�20

Page 21: PHP e seus demônios

�21

CRIANDO  UM  DAEMON

Page 22: PHP e seus demônios

Passo  a  passo

1. Fork  off  and  die  2. Máscara  de  criação  dos  arquivos  3. Entradas  e  saídas  4. Logging  5. Desligar  sessão  (SID)  6. Working  directory  7. Locking

�22

Page 23: PHP e seus demônios

Fork  off  and  die

• Você  apenas  criará  o  fork  e  encerrará  imediatamente  o  processo  pai  

• O  processo  filho  será  o  daemon,  executando  em  background

�23

Page 24: PHP e seus demônios

Daemons/fork.php<?php$pid = pcntl_fork();if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2);!} elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit();}!while (true) { mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); sleep(2);}

�24

Page 25: PHP e seus demônios

Máscara  de  criação  dos  arquivos

• Para  garantir  que  você  possa  ler  e  escrever  arquivos  restaure  o  umask  para  o  padrão  do  sistema,  com  umask(0)

�25

Page 26: PHP e seus demônios

Daemons/fork+umask.php<?php$pid = pcntl_fork();if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2);!} elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit();}!umask(0);!while (true) { mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); sleep(2);}

�26

Page 27: PHP e seus demônios

Entradas  e  saídas

• O  daemon  não  possui  interação  com  o  usuário,  portanto  você  não  deve  permitir  que  os  métodos  de  entrada  e  saída  (STDIN,  STDOUT  e  STDERR)  sejam  utilizados  

• Você  pode  fechar  STDIN,  STDOUT  e  STDERR,  mas  caso  você  esteja  utilizando  essas  constantes  com  certeza  você  terá  problemas  

• Você  também  pode  utilizar  as  funções  ob_*  para  evitar  outputs

�27

Page 28: PHP e seus demônios

Daemons/fork+umask+file_descriptors.php<?php$pid = pcntl_fork();if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2);!} elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit();}!umask(0);!fclose(STDIN);fclose(STDOUT);fclose(STDERR);!$fd0 = fopen('/dev/null', 'r');$fd1 = fopen('/tmp/psd.log', 'a');$fd2 = fopen('php://stdout', 'a');!while (true) { mail('vagrant@localhost', 'Lorem ipsum', 'Dolor sit amet'); sleep(2);}

�28

Page 29: PHP e seus demônios

Logging

• Visto  que  não  interação  entre  o  daemon  e  o  usuário,  logs  são  uma  ótima  forma  de  obter  feedback  de  um  daemon  

• Você  pode  fazer  logs  em:  ‣ Arquivos  ‣ Bancos  de  dados  relacionais  ‣ Bancos  de  dados  não-­‐relacionais  ‣ Message  Queue  ‣ Syslog  ‣ …

�29

Page 30: PHP e seus demônios

Daemons/fork+umask+file_descriptors+logging.php<?php$pid = pcntl_fork();if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2);!} elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit();}!umask(0);!fclose(STDIN);fclose(STDOUT);fclose(STDERR);!$fd0 = fopen('/dev/null', 'r');$fd1 = fopen('/tmp/psd.log', 'a');$fd2 = fopen('php://stdout', 'a');!openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0);while (true) { syslog(LOG_DEBUG, 'Envio de email iniciando'); $sent = mail('vagrant@localhost', 'Lorem ipsum', 'Lorem ipsum dolor sit amet'); if (true === $sent) { syslog(LOG_DEBUG, 'Envio de email terminado sucesso'); continue; } syslog(LOG_ERR, 'Falha ao enviar email'); sleep(2);}closelog();

�30

!

Page 31: PHP e seus demônios

Desligar  sessão  (SID)

• Mesmo  que  o  processo  filho  seja  executado  em  background,  não  dependendo  do  processo  pai,  eles  estão  na  mesma  sessão  

• Quando  a  sessão  terminar  (o  terminal  fechado,  por  exemplo),  o  sistema  matará  o  processo  filho  

• A  função  posix_setsid()  cria  uma  nova  sessão  para  o  processo  filho,  desvinculando-­‐o  do  processo  pai  e  sua  sessão  

• O  processo  filho  passa  a  ter  o  init  (processo  inicial  que  carrega  todos  os  outros  processos  do  sistema)  como  processo  pai

�31

Page 32: PHP e seus demônios

Daemons/fork+umask+file_descriptors+logging+detach_sid.php<?php$pid = pcntl_fork();if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2);!} elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit();}!umask(0);!fclose(STDIN);fclose(STDOUT);fclose(STDERR);!$fd0 = fopen('/dev/null', 'r');$fd1 = fopen('/tmp/psd.log', 'a');$fd2 = fopen('php://stdout', 'a');!openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0);!if (posix_setsid() < 0) { syslog(LOG_ERR, 'Não foi possível desvincular processo de sua sessão'); exit(2);}!while (true) { /** Payload **/ }closelog();

�32

Page 33: PHP e seus demônios

Working  directory

• O  filho  herda  o  working  directory  do  pai  • Este  working  directory  pode  ser  um  volume  montado  que  pode  ser  desmontado  em  algum  momento  

• Para  desmontar  um  volume  o  sistema  irá  matar  qualquer  processo  que  ainda  está  usando  o  diretório

�33

Page 34: PHP e seus demônios

Daemons/fork+umask+file_descriptors+logging+detach_sid+chdir.php<?php$pid = pcntl_fork();if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(2);!} elseif ($pid > 0) { echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit();}!umask(0);!fclose(STDIN);fclose(STDOUT);fclose(STDERR);!$fd0 = fopen('/dev/null', 'r');$fd1 = fopen('/tmp/psd.log', 'a');$fd2 = fopen('php://stdout', 'a');!openlog('PSD', LOG_PID | LOG_CONS, LOG_LOCAL0);!if (posix_setsid() < 0) { syslog(LOG_ERR, 'Não foi possível desvincular processo de sua sessão'); exit(2);}!chdir(__DIR__);!while (true) { /** Payload **/ }closelog();

�34

Page 35: PHP e seus demônios

pidfile

• Contém  o  PID  do  daemon  • Impede  que  o  daemon  seja  executado  mais  de  uma  vez

�35

Page 36: PHP e seus demônios

�36Gene

rated  by  https://w

ww.lucidchart.com

Page 37: PHP e seus demônios

Daemons/fork+umask+file_descriptors+logging+detach_sid+chdir+pidfile.php<?php!$pidfile = '/var/run/psd/daemon.pid';if (file_exists($pidfile)) { $daemonPid = (int) file_get_contents($pidfile); if (true === posix_kill($daemonPid, 0)) { echo 'Daemon já em execução (PID ' . $daemonPid . ').' . PHP_EOL; exit(2); } unlink($pidfile);}!$pidfileHandler = fopen($pidfile, 'w+');!if (! flock($pidfileHandler, LOCK_EX | LOCK_NB)) { echo 'Falha ao bloquear acesso externo ao pidfile' . PHP_EOL; exit(3);}!$pid = pcntl_fork();if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL; exit(4);!} elseif ($pid > 0) { if (! fwrite($pidfileHandler, $pid)) { echo 'Falha ao escrever PID no pidfile' . PHP_EOL; exit(5); }! echo 'Daemon inicializado (PID: ' . $pid . ').' . PHP_EOL; exit();}!register_shutdown_function('unlink', $pidfile); !// Corpo do daemon

�37

Page 38: PHP e seus demônios

SPAWN

�38

Page 39: PHP e seus demônios

• Muito  utilizado  no  processamento  de  filas  quando  você  precisa  de  processos  concorrentes  

• Um  processo  pode  criar  outros  processos  e  delegar  tarefas  para  cada  um  deles  

• Esse  recurso  muitas  vezes  é  confundido  com  multi-­‐threading,  mas  não  é  isso.  O  PHP  não  possui  suporte  a  este  recurso  mas  existe  uma  extensão  PECL  para  isso  

• Geralmente  os  processos  pai  são  daemons  sendo  seus  filhos  workers  

• Você  não  pode  alterar  o  SID  dos  filhos  pois  você  precisa  deles  na  mesma  sessão  do  processo  pai

�39

Page 40: PHP e seus demônios

Spawn/exemplo.php<?php$pid = pcntl...// Fluxo normal do daemon!$childrenLimit = 10;$childrenPids = array();while (true) { if (count($childrenPids) >= $childrenLimit) { $firstChildPid = array_shift($childrenPids); pcntl_waitpid($firstChildPid, $status); }! $childPid = pcntl_fork();! if ($childPid == -1) { syslog(LOG_ERR, 'Falha ao criar filho'); continue; }! if ($childPid > 0) { $childrenPids[] = $childPid; continue; }! syslog(LOG_DEBUG, 'Envio de email iniciando'); $sent = mail('vagrant@localhost', 'Lorem ipsum', 'Lorem ipsum dolor sit amet'); if (true === $sent) { syslog(LOG_DEBUG, 'Envio de email terminado sucesso'); exit(0); } syslog(LOG_ERR, 'Falha ao enviar email'); exit(3);}closelog();

�40

Page 41: PHP e seus demônios

ZOMBIES

�41

Page 42: PHP e seus demônios

• Um  processo  zombie  é  um  processo  que  já  foi  completamente  executado  mas  ainda  se  encontra  na  tabela  de  processos  do  SO,  permitindo  que  o  processo  que  o  criou  leia  o  seu  valor  de  saída  

• Quando  um  processo  termina,  a  memória  a  ele  associada  é  libertada,  no  entanto  a  informação  sobre  esse  processo  continua  disponível,  embora  ele  já  não  exista  

• Normalmente  os  processos  zombie  não  duram  muito  tempo  já  que  o  sinal  SIGCHLD  é  emitido  quando  ele  entra  nesse  estado,  possibilitando  ao  processo  pai  saber  quando  isso  acontece  para  ler  as  informações  necessárias  

• Se  o  processo  pai  explicitamente  ignora  o  SIGCHLD  definindo  seu  manipulador  como  SIG_IGN  todos  as  informações  de  término  dos  processos  filhos  serão  descartadas  e  os  processos  zombies  continuarão  na  tabela

�42

Page 43: PHP e seus demônios

Zombies/reaper.php<?php!function reaper($signal){ if ($signal != SIGCHLD) { return; }! while (pcntl_waitpid(-1, $status, WNOHANG | WUNTRACED) > 0) { usleep(1000); }}!pcntl_signal(SIGCHLD, 'reaper');

�43

Page 44: PHP e seus demônios

Inter-­‐Process  Communication

IPC

�44

Page 45: PHP e seus demônios

• Cada  processo  possui  um  contexto  de  execução  próprio.  Um  processo  não  tem  conhecimento  do  contexto  de  outro  processo  sendo  assim  os  processos  não  conseguem  transferir  informação  entre  si  

• Inter-­‐Process  Communication  (IPC),  é  o  grupo  de  mecanismos  que  permite  aos  processos  transferirem  informação  entre  si  

• Usando  IPC  um  processo  pai  consegue  obter  informações  precisar  de  seus  filhos  

• Para  IPC  podemos  utilizar:  ‣ Arquivos  ‣ Filas  de  mensagens  ‣ Memória  Compartilhada  ‣ Sinais  ‣ Par  de  Sockets  ‣ …

�45

Page 46: PHP e seus demônios

Arquivos

• Você  pode  escrever  dados  em  um  processo  e  ler  em  outro  processo,  desde  que  ambos  tenham  permissão  de  leitura  

• Nome  do  arquivo  deve  ser  único

�46

Page 47: PHP e seus demônios

IPC/file.php<?php!$filename = '/tmp/' . getmypid() . '.ipc';if (! is_file($filename)) { touch($filename);}!$dataWritten = 'PHP e seus Demônios';if (false === file_put_contents($filename, $dataWritten)) { echo 'Falha ao gravar dados no arquivo' . PHP_EOL; exit(2);}!$dataGiven = file_get_contents($filename);if (false === $dataGiven) { echo 'Falha ao ler dados no arquivo' . PHP_EOL; exit(3);}!echo 'Dado lido no arquivo: ' . $dataGiven . PHP_EOL;!if (! unlink($filename)) { echo 'Falha ao tentar remover o arquivo' . PHP_EOL; exit(3);}

�47

Page 48: PHP e seus demônios

Memória  compartilhada• É  um  fácil  caminho  para  usar  funções  que  permitem  o  PHP  ler,  escrever,  criar  e  deletar  segmentos  de  memória  compartilhada  UNIX  

• O  PHP  possui  duas  API’s,  as  funções  shmop_*  e  shm_*:    • Para  habilitar  as  funções    shmop_*    é  preciso  compilar  o  PHP  com  a  opção  --enable-shmop  do  configure  

• Para  habilitar  as  funções    shm_*    é  preciso  compilar  o  PHP  com  a  opção  --enable-sysvshm  do  configure  

• Funciona  basicamente  com  uma  chave,  por  ela  você  pode  ler  e  escrever  dados  na  memória  

• Utilize  o  comando  ipcs  para  monitorar  os  seguimentos  criados  e  ipcrm shm ID  para  remover  seguimentos  (você  também  pode  usar  ipcmk  para  criar  seguimentos)

�48

Page 49: PHP e seus demônios

IPC/shmop.php<?php!$key = getmypid();$flag = 'c';$permission = 0644;$memorySize = 1024;!$shmId = shmop_open($key, $flag, $permission, $memorySize);if (! $shmId) { echo 'Não foi possível criar o segmento de memória' . PHP_EOL; exit(1);}!$stringWritten = 'PHP e seus demônios';$shmBytesWritten = shmop_write($shmId, $stringWritten, 0);if ($shmBytesWritten != strlen($stringWritten)) { echo 'Não foi possível gravar o dado e com seu tamanho correto' . PHP_EOL; exit(2);}!$stringRead = shmop_read($shmId, 0, $memorySize);if (! $stringRead) { echo 'Não foi possível ler o dado na memória compartilhada' . PHP_EOL; exit(2);}!echo 'Dado lido na memória compartilhada foi: ' . $stringRead . PHP_EOL;!if (! shmop_delete($shmId)) { echo 'Não foi possível marcar o bloco de memória compartilhada para remoção';}!shmop_close($shmId);

�49

Page 50: PHP e seus demônios

IPC/shm.php<?php!$key = getmypid();$permission = 0644;$memorySize = 1024;!$shmId = shm_attach($key, $memorySize, $permission);if (! $shmId) { echo 'Falha ao criar o segmento de memória' . PHP_EOL; exit(1);}!$stringWritten = 'PHP e seus demônios';if (! shm_put_var($shmId, 1, $stringWritten)) { echo 'Falha ao gravar o dado na memória compartilhada' . PHP_EOL; exit(2);}!if (! shm_has_var($shmId, 1)) { echo 'Nenhum dado na chave 1 foi encontrado na memória' . PHP_EOL; exit(2);}!$stringRead = shm_get_var($shmId, 1);if (! $stringRead) { echo 'Falha ao ler o dado da chave 1 na memória compartilhada' . PHP_EOL; exit(2);}!echo 'Dado lido na memória compartilhada foi: ' . $stringRead . PHP_EOL;!if (! shm_remove($shmId)) { echo 'Falha ao remover do bloco de memória compartilhada';}!if (! shm_detach($shmId)) { echo 'Falha ao se desconectar do bloco de memória compartilhada';}

�50

Page 51: PHP e seus demônios

Filas  de  mensagens

• O  PHP  possui  suporte  a  filas  de  mensagens  do    • Para  habilitar  as  funções    msg_*    é  preciso  compilar  o  PHP  com  a  opção  --enable-sysvmsg  do  configure  

• Utilize  o  comando  ipcs  para  monitorar  os  seguimentos  criados  e  ipcrm msg ID  para  remover  seguimentos  (você  também  pode  usar  ipcmk  para  criar  seguimentos)

�51

Page 52: PHP e seus demônios

IPC/msg.php<?php!$key = getmypid();$messageQueueId = msg_get_queue($key);!$messageSent = 'PHP e seus demônios';$messageWasSent = msg_send($messageQueueId, 2, $messageSent);if (! $messageWasSent) { echo 'Falha ao enviar mensagem' . PHP_EOL; exit(2);}!if (! msg_receive($messageQueueId, 2, $msgType, 1024, $messageReceived, true, 0, $error)) { echo 'Falha ao ler mensagem' . $error . PHP_EOL; exit(3);}echo 'Mensagem recebida: ' . $messageReceived . PHP_EOL;!if (! msg_remove_queue($messageQueueId)) { echo 'Falha ao remover fila de mensagens'. PHP_EOL; exit(3);}

�52

Page 53: PHP e seus demônios

Par  de  sockets

• Dois  sockets  conectados  armazenados  em  um  array  

• Conexão  de  duas  vias,  as  mensagens  são  entregues  no  mesmo  instante

�53

Page 54: PHP e seus demônios

IPC/msg.php<?php!$sockets = array();!if (false === socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) { echo 'Falha ao criar par de sockets: ' . socket_strerror(socket_last_error()) . PHP_EOL;}!$pid = pcntl_fork();if ($pid == -1) { echo 'Falha na criação do fork' . PHP_EOL;} elseif ($pid > 0) {! socket_close($sockets[0]); $messageWritten = 'Mensagem enviada pelo processo pai'; if (false === socket_write($sockets[1], $messageWritten, strlen($messageWritten))) { echo 'Falha ao escrever dados no socket: ' . socket_strerror(socket_last_error($sockets)); exit(3); }! $messageGiven = socket_read($sockets[1], 1024, PHP_BINARY_READ);! echo 'Mensagem no processo pai: ' . "\t" . $messageGiven . PHP_EOL; socket_close($sockets[1]);!} else {! socket_close($sockets[1]); $messageWritten = 'Mensagem enviada pelo processo filho'; if (false === socket_write($sockets[0], $messageWritten, strlen($messageWritten))) { echo 'Falha ao escrever dados no socket: ' . socket_strerror(socket_last_error($sockets)); exit(3); }! $messageGiven = socket_read($sockets[0], 1024, PHP_BINARY_READ);! echo 'Mensagem no processo filho: ' . "\t" . $messageGiven . PHP_EOL; socket_close($sockets[0]);}

�54

Page 55: PHP e seus demônios

Outras  formas

• APC  • Memcached  • MongoDB  • MySQL  • RabbitMQ  • Redis  • SQLite  • …

�55

Page 56: PHP e seus demônios

PERFORMANCE

�56

Page 57: PHP e seus demônios

• Não  existe  garbage  collection,  o  processo  principal  não  morre  

• Utilize  as  funções  gc_enable()  e  gc_collect_cycles()  

• O  PHP  possui  um  cache  padrão  de  arquivos  abertos  (em  memória)  isso  pode  prejudicar  a  performance  do  daemon,  utilize  clearstatcache()  para  remover  esse  cache  

• Utilizar  IPC  sem  limpar  os  dados  corretamente  pode  ocasionar  uma  série  de  problemas

�57

Page 58: PHP e seus demônios

BIBLIOTECAS

�58

Page 59: PHP e seus demônios

• Arara\Process  (https://github.com/Arara/Proccess)  

• PHP-­‐Daemon  (https://github.com/shaneharter/PHP-­‐Daemon)  

• System_Daemon  (http://pear.php.net/package/System_Daemon)  

• ZendX_Console_Process_Unix  (http://framework.zend.com/manual/1.12/en/zendx.console.process.unix.html)

�59

Page 60: PHP e seus demônios

PERGUNTAS

�60

Page 61: PHP e seus demônios

CONCLUSÃO

�61

Page 62: PHP e seus demônios

Links

• @henriquemoody  na  maioria  das  redes  sociais  (about.me,  BitBucket,  Coderbits,  GitHub,  SlideShare,  Twitter…)  

• Código  da  palestra:  https://github.com/henriquemoody/php-­‐e-­‐seus-­‐demonios/tree/1.0.0  

• Ícones:  http://www.visualpharm.com  • Formatação  de  código:  https://sublime.wbond.net/packages/Highlight

�62

Page 63: PHP e seus demônios

Referências• http://en.wikipedia.org/wiki/Cron  • http://en.wikipedia.org/wiki/Daemon_(computing)  • http://en.wikipedia.org/wiki/Init  • http://en.wikipedia.org/wiki/POSIX  • http://man7.org/linux/man-­‐pages/man7/signal.7.html  • http://php.net/ChangeLog-­‐4.php  • http://php.net/cli  • http://php.net/ncurses  • http://php.net/newt  • http://php.net/pcntl  • http://php.net/posix  • http://php.net/readline  • http://pt.wikipedia.org/wiki/Daemon_(computação)  • http://www.slideshare.net/jkeppens/php-­‐in-­‐the-­‐dark  • http://www.win.tue.nl/~aeb/linux/lk/lk-­‐10.html

�63