Moodle não converte o PDF da tarefa: o erro do exec e como resolver

Moodle não converte o PDF da tarefa: o erro do exec e como resolver

Resposta rápida: Se o professor não consegue anotar o PDF da entrega e o registro mostra "Call to undefined function assignfeedback_editpdf\exec()", o PHP do servidor está com a função exec desativada. O Moodle precisa dela para chamar o Ghostscript. Libere somente exec na configuração do PHP, teste o Ghostscript e reprocesse as conversões pendentes. As entregas dos alunos não se perdem.

O aluno entregou a tarefa em PDF, a entrega aparece como enviada, mas na hora de corrigir o professor não vê o documento para anotar, ou vê um aviso de que a conversão ainda está pendente. Dias depois, continua pendente. O problema quase nunca está na tarefa nem no arquivo do aluno: está no servidor.

O sintoma

  • Na tela de avaliação, o documento da entrega não carrega para anotação, ou fica em espera.
  • A entrega do aluno aparece normalmente como enviada, com o arquivo anexado.
  • Nos registros de tarefas do Moodle aparecem falhas repetidas da conversão de entregas, com a mensagem "Call to undefined function assignfeedback_editpdf\exec()".

Como o Moodle prepara o PDF

Fluxo em quatro passos: o aluno envia a tarefa; uma tarefa em segundo plano executada pelo cron faz a conversão e tenta de novo se falhar; o PHP chama o Ghostscript com a função exec e, se ela estiver desativada, o processo para; o PDF fica pronto para o professor anotar.
O passo 3 é onde a conversão trava quando o PHP tem a função exec desativada.

O recurso de anotar PDF da tarefa não trabalha com o arquivo original. Em segundo plano, numa tarefa executada pelo cron, o Moodle converte a entrega em imagens de página usando o Ghostscript, um programa instalado no servidor. Para chamar esse programa, o PHP usa a função exec. Se a tarefa falha, o Moodle tenta de novo mais tarde, e por isso o mesmo erro aparece várias vezes no registro.

Entregas em outros formatos, como Word, ainda passam antes por um conversor de documentos configurado no Moodle. Este artigo trata do caso mais comum: PDF que não chega a ser processado.

Diagnóstico em 4 passos

  1. Confirme que o cron está rodando. Sem cron, nenhuma conversão acontece. Veja cron do Moodle que não roda.
  2. Olhe as tarefas em segundo plano. Em Administração do site > Servidor > Tarefas, procure as tarefas ad hoc de conversão de entregas e o registro das que falharam. A mensagem de erro diz a causa.
  3. Teste o Ghostscript. Nas configurações do plugin de feedback de anotação de PDF da tarefa, há um teste do caminho do Ghostscript. Se ele falhar, o problema é o caminho do programa ou a permissão para executá-lo.
  4. Leia a mensagem com atenção. "Call to undefined function ... exec()" não quer dizer que falta código no Moodle: quer dizer que o PHP desativou a função.

A causa: exec desativado no PHP

Muitas hospedagens incluem exec na diretiva disable_functions do PHP, por segurança. A partir do PHP 8, uma função desativada é removida da tabela de funções, segundo o manual do PHP: para o código, é como se ela não existisse. Daí a mensagem de "função indefinida", que confunde quem procura um arquivo faltando no Moodle.

Repare que o Ghostscript pode estar instalado e funcionando no servidor. O que falta é a permissão para o PHP chamá-lo.

Como corrigir sem abrir mais do que o necessário

  1. Retire somente exec da lista disable_functions, no painel de configuração de PHP da hospedagem ou no php.ini do servidor. Mantenha as outras funções desativadas.
  2. Não tente pelo código. A diretiva disable_functions é de sistema: ini_set e arquivos .user.ini não a alteram. Também não vale criar um substituto de exec dentro do Moodle.
  3. Confira o PHP certo. As conversões rodam pelo cron, que usa o PHP de linha de comando. Ele pode ter configuração diferente do PHP do site.
  4. Teste o Ghostscript de novo pelo teste do plugin.
  5. Reprocesse as pendentes. As tarefas com falha são tentadas de novo pelo cron. Para não esperar, o administrador pode executar uma tarefa específica com php admin/cli/adhoc_task.php --id=NÚMERO.
  6. Confirme na tela de avaliação que o documento aparece para anotar.

Num caso real: 35 falhas, 6 entregas

Numa plataforma de cursos recém-atualizada para o Moodle 4.5, os professores pararam de conseguir anotar as entregas. O registro de um dia mostrava 35 execuções com falha. Parecia um desastre, mas eram só 6 entregas, com várias tentativas cada. As seis estavam registradas como enviadas, cada uma com o seu arquivo: nada tinha se perdido.

O Ghostscript estava instalado e executável; o PHP tinha exec desativado. O administrador retirou apenas exec da lista, no painel da hospedagem. Com a função disponível no PHP de linha de comando e o teste do Ghostscript aprovado, rodamos somente as seis tarefas pendentes. As seis converteram, a fila de conversões zerou e as entregas mantiveram status e data de envio, sem nenhuma nota alterada.

A lição: contar falhas não é contar entregas perdidas. Antes de pedir aos alunos que reenviem, confira o que realmente está pendente. Uma hospedagem preparada para o Moodle já deixa o PHP ajustado para isso. Veja o que verificar ao contratar hospedagem para Moodle.

Perguntas frequentes

Por que o Moodle não mostra o PDF da entrega para anotar?

Porque a conversão em segundo plano não terminou. As causas mais comuns são cron parado, Ghostscript não encontrado ou a função exec desativada no PHP do servidor.

O que significa "Call to undefined function assignfeedback_editpdf\exec()"?

Que o PHP está com a função exec desativada em disable_functions. A partir do PHP 8, funções desativadas são removidas da tabela de funções, e o código passa a vê-las como inexistentes.

Os alunos precisam reenviar a tarefa?

Normalmente não. A entrega fica registrada mesmo quando a conversão falha. Depois de corrigir o servidor, as conversões pendentes podem ser reprocessadas.

Liberar o exec no PHP é seguro?

Libere somente o exec, mantendo as demais funções desativadas, e mantenha o servidor e o Moodle atualizados. O Moodle usa essa função para chamar programas como o Ghostscript.

Dá para mudar o disable_functions pelo .user.ini?

Não. É uma diretiva de sistema: só muda no php.ini do servidor ou no painel de configuração de PHP da hospedagem.

Alejandro Argachá, especialista em Moodle

Escrito por Alejandro Argachá

Conhece o Moodle desde 2011 e, desde 2016, atua na parte técnica: servidor, código e segurança. Mais de 250 projetos entregues, boa parte para outras empresas que vendem Moodle. Resolve na prática problemas como este em plataformas de empresas e instituições brasileiras. Ver casos reais.