Aller au contenu

Un crontab fait planter un script php d'envoi de mails


renaud63

Sujets conseillés

Bonjour à tous,

J'ai un système de newsletter sur mon site qui utilise la classe PHP Mailer.

Le serveur est un VPS dédié Plesk / Centos

La fonction utilisée pour les envois est sendmail().

Sendmail semble bien installé.

Si j'exécute le script via le navigateur, tout se passe bien, les emails partent et s'affichent à l'écran.

Mais là où ça coince, c'est lorsque je fais exécuter le script par un crontab.

Rien ne part et j'ai l'erreur (dans l'email envoyé par le crontab à l'admin système):

toto_AT_gmail.com<br>sh: /sendmail: No such file or directory

La commande crontab est formulée comme suit :


/usr/bin/php /var/www/vhosts/mon-site.com/httpdocs/script_envoi.php

Dans le code de la page, avant la balise PHP, j'ai inséré :


:/usr/bin/php

Il doit bien y avoir une erreur au niveau de la commande...et du chemin de sendmail qu'il ne trouve pas.

Merci de vos conseils.

Lien vers le commentaire
Partager sur d’autres sites

Le grand classique avec cron c'est que l'environnement n'est pas le même, en particulier $PATH, et le php.ini utilisé n'est pas forcément le même (lance un cron avec un phpinfo dedans, et compare le résultat avec ce que dit phpinfo via apache).

Ceci dit j'ai du mal à comprendre comment il arrive à "/sendmail". C'est quelle version de PHPMailer, est-ce-que manipules la propriété $Sendmail?

Jacques.

Lien vers le commentaire
Partager sur d’autres sites

Posté (modifié)

Bonjour Jacques,

Voici le comparatif du phpinfo de cron et de apache (se sachant trop quelle donnée comparer, j'ai relevé le sendmail path:

- Via cron : /usr/sbin/sendmail -t -i

- Apache : /usr/sbin/sendmail -t -i

Idem, donc. Maintenant, je ne compare peut-être les bonnes données...

Oup's ! j'avais mal lu ton post ! le php.ini est /etc/php.ini dans les deux cas.

- Concernant PHPMailer, j'utilise la dernière version : 5.1 pour PHP 5

- Oui j'utilise sendmail pour les envois, et la var $Sendmail est : /usr/sbin/sendmail (j'ai laissé le par défaut).

Merci.

Renaud.

Modifié par renaud63
Lien vers le commentaire
Partager sur d’autres sites

Bizarre... Ajoute une trace (avec un echo ou un error_log) à la ligne 604 de class.phpmailer.php (dans la fonction SendmailSend, juste avant "if ($this->SingleTo === true)"), pour voir la valeur de $sendmail à cet endroit-là.

Ca donne quoi un "ls -l /usr/sbin/sendmail" et un "file /usr/sbin/sendmail"? C'est un binaire ou un shell qui sert de wrapper autour de quelque chose d'autre?

Jacques.

Lien vers le commentaire
Partager sur d’autres sites

Le echo $sendmail donne :

/usr/sbin/sendmail -oi -f 'bounces_AT_autorepondeur-fr.com' -t

L'adresse email est celle de ma boite de bounces (définie dans la variable $Sender - le return-path)

La commande "ls -l /usr/sbin/sendmail" donne :

lrwxrwxrwx 1 root root 21 Oct 30 2008 /usr/sbin/sendmail -> /etc/alternatives/mta

La commande "file /usr/sbin/sendmail" donne

/usr/sbin/sendmail: symbolic link to `/etc/alternatives/mta'

Lien vers le commentaire
Partager sur d’autres sites

Et ls -l /etc/alternatives/mta et file /etc/alternatives/mta (et ainsi de suite si c'est encore un lien symbolique, ce qu'il devrait être)?

Normalement ce sont des liens symboliques vers /usr/sbin/sendmail.sendmail ou un truc du genre, mais je pense qu'il y a quelque part un wrapper en shell qui fait appel à une variable d'environnement qui n'existe pas par défaut via cron.

Jacques.

Lien vers le commentaire
Partager sur d’autres sites

/etc/alternatives/mta -> /usr/sbin/sendmail.postfix

/etc/alternatives/mta: symbolic link to `/usr/sbin/sendmail.postfix'

Puis

-l /usr/sbin/sendmail.postfix : command not found -l

file /usr/sbin/sendmail.postfix/usr/sbin/sendmail.postfix: ELF 64-bit LSB shared object, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, stripped

Est ce que ça veut dire que je dois rajouter .postfix à la variable $Sendmail ?

Lien vers le commentaire
Partager sur d’autres sites

Non, normalement tout ça est transparent (ça veut juste dire que c'est en fait postfix et pas sendmail qui est utilisé).

Il y a quelque part quelque chose qui convertit "/usr/sbin/sendmail" en "/sendmail", mais je ne sais pas trop quoi. Peut-être quelque-chose du côté de safe_mode ou safe_mode_exec_dir, mais j'aurais eu tendance à penser que ça ferait une erreur plus explicite.

Fais une vérification exhaustive des différences entre les phpinfo en cron et via apache (avec un bon diff par exemple), c'est forcément quelque part là-dedans...

Jacques.

Lien vers le commentaire
Partager sur d’autres sites

Euh....excuse moi, mais qu'entends-tu par "diff" ? Une commande linux ? comment l'utiliser ?

Le phpinfo de cron est dans un email et celui de apache dans le navigateur.

Lien vers le commentaire
Partager sur d’autres sites

man diff :-)

Tu colles le source de la page/du mail généré par phpinfo chacun dans un fichier, et:

diff -u fichier1 fichier2

Sinon tu peux toujours te palucher les deux à la main pour trouver les différences...

Jacques.

Lien vers le commentaire
Partager sur d’autres sites

:fou: ? me palucher les deux fichiers...ah ah ah...y'a au moins 12 000 lignes !

Bon j'ai capté diff, mais le problème, c'est que ce qui m'a été envoyé dans le mail du cron est en vrac tandis que la source navigateur est joliment pleine de <td> et autres balises HTML. Donc diff va en trouver un paquets, des diff !

Donc faut que je fasse en sorte que le cron me copie la source phpinfo dans un txt...

Je fais ça et je te dis.

Lien vers le commentaire
Partager sur d’autres sites

Bon...alors, je me suis bien cassé la tête pour obtenir 2 fichiers comparables !

Voici comment j'ai procédé :

- la commande echo "<?php phpinfo()?>" | php > /tmp/test_php_apache.txt a copié le phpinfo apache en brut dans le fichier test_php_apache.txt

- j'ai copié le contenu du mail cron php info dans un autre txt, puis placé dans tmp également

- Puis la commande que tu m'as donnée : diff -u /tmp/phpinfo_cron.txt /tmp/test_php_apache.txt

Et un la console a...comment dire ? vomi un flot de données.

Alors ma question est : est-ce qu'il y a une zone, ou certaines données, à comparer plus particulièrement ou a te coller ici ?

Lien vers le commentaire
Partager sur d’autres sites

Le premier te donne le phpinfo pour un php executé en ligne de commande, ce n'est pas forcément pareil qu'avec Apache ou avec cron. D'ailleurs, quand tu lances ton script depuis le shell plutôt que via cron, ça marche ou pas?

Pour obtenir le phpinfo httpd:

Fichier phpinfo.php avec <?php phpinfo()?>

curl http://tonserveur/chemin_vers_phpinfo.php >phpinfo_httpd

ou

wget http://tonserveur/chemin_vers_phpinfo.php

(dans ce dernier cas le fichier résultat s'appelerra phpinfo.php)

Pour obtenir le phpinfo cron: mettre en cron php /chmein/ver/phpinfo.php >phpinfo_cron

Ensuite diff -u phpinfo_httpd phpinfo_cron

Les parties importantes c'est la fin ($_ENV surtout, éventuellement $_SERVER) et tout ce qui est safe_mode_quelque_chose.

Jacques.

Lien vers le commentaire
Partager sur d’autres sites

Posté (modifié)

Un petit pb et une question :

ces deux fichiers phpinfo_httpd et phpinfo_cron... ils vont se créer où ? :huh:

Je demande ça, parce que :

J'ai saisi, pour le cron, la commande: php /var/www/vhosts/autorepondeur-fr.com/httpdocs/version.php>phpinfo_cron

version.php étant le fichier qui contient <?php phpinfo(); ?>

Mais le rapport par email me donne :

/bin/sh: phpinfo_cron: Permission denied

Je précise que safe_mode est à off. Ai-je quelque dossier à chmoder ?

Et je te remercie encore pour ta patience et ta compétence.

Si tu me donnes ton adresse en MP, moi je t'envoie une bouteille de champ' (en espérant que tu n'habites pas de l'autre côté de la planète, lol)

EDIT : ahrggghh ! j'ai compris, je pense ! je vois que le fichier phpinfo_httpd s'est crée dans /root

je présume qu'il en est de même pour l'autre. Et la tâche cron s'exécute depuis le domaine, donc pas en root.

Je recommence.

Modifié par renaud63
Lien vers le commentaire
Partager sur d’autres sites

Posté (modifié)

Bon, cette fois les deux dossiers se sont bien crées.

J'ai donc fait: diff -u phpinfo_httpd phpinfo_cron

Mais j'ai l'impression, vu l'avalanche de données, que tout le contenu s'est affiché.

diff est sensé n'afficher que ce qui est différent (comme son nom l'indiquerait) ?

EDIT : oui je confirme. Je fais : diff -u phpinfo_httpd phpinfo_cron > /tmp/diff.txt

Et dans diff.txt, il y a le contenu complet du phpinfo();

Modifié par renaud63
Lien vers le commentaire
Partager sur d’autres sites

Aucun des deux fichiers n'est vide? Il doit y avoir un problème de format légèrement différent, tu peux essayer en rajoutant les flags -iwbB (diff -uiwbB fichier1 fichier2).

Au fait, quand tu dis que tu mets tes commandes en cron, dans quel cron? Celui d'un utilisateur, pas celui de root ou le cron système, j'espère?

Jacques.

Lien vers le commentaire
Partager sur d’autres sites

La commande -iwbB (diff -uiwbB phpinfo_httpd phpinfo_cron)

retourne : -bash: syntax error near unexpected token `diff'

Euh, pour ta question : ben si, j'ai crée la tâche au niveau du serveur avec l'utilisateur root. C'est grave docteur ?

Comme je te disais l'autre jour lors de notre précédent échange de posts, je n'héberge personne (et heureusement pour eux !).

Donc le domaine, c'est à moi.

Et quand j'ai crée cette tâche dans le domaine : permission denied.

:blushing:

Lien vers le commentaire
Partager sur d’autres sites

la commande c'est "diff -uiwbB fichier1 fichier2"...

Et oui, ce n'est pas une bonne idée de faire tourner quoi que ce soit en root si ce n'est pas indispensable. D'ailleurs j'espère au moins que tu ne te connectes pas en tant que root, mais bien comme un utilisateur normal, et que tu utilises su pour faire les manips utiles. Et quand tu es connecté comme utilisateur normal, tu fais un crontab -e, et voilà. Evidemment il faut que les fichiers nécessaires soient exécutables par cet utilisateur...

Jacques.

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

Et bien j'ai ressaisi la commande "diff", et, une fois de plus, un gros volume de données s'est affiché. Tout le phpinfo(), en fait.

Je pense en connaître la raison : le fichier phpinfo_cron est brut, tandis que phpinfo_httpd est formaté HTML. De ce fait, toutes les lignes sont différentes. J'ai pu isoler la partie finale des deux fichiers et nettoyer le HTML. Voici quelques unes des différences que j'ai pu noter. Je peux t'envoyer le fichier diff.rtf en MP si tu veux.

CRON :

_SERVER["SHELL"] => /bin/sh

_SERVER["USER"] => root

_SERVER["PATH"] => /usr/bin:/bin

_SERVER["PWD"] => /root

_SERVER["SHLVL"] => 1

_SERVER["HOME"] => /root

_SERVER["LOGNAME"] => root

_SERVER["_"] => /usr/bin/php

_SERVER["argc"] => 1

_ENV["SHELL"] => /bin/sh

_ENV["USER"] => root

_ENV["PATH"] => /usr/bin:/bin

_ENV["PWD"] => /root

_ENV["SHLVL"] => 1

_ENV["HOME"] => /root

_ENV["LOGNAME"] => root

_ENV["_"] => /usr/bin/php

HTTPD :

_SERVER["PATH"]/sbin:/usr/sbin:/bin:/usr/bin

_ENV["CONSOLE"]/dev/null

_ENV["SELINUX_INIT"]YES

_ENV["TERM"]linux

_ENV["INIT_VERSION"]sysvinit-2.86

_ENV["PATH"]/sbin:/usr/sbin:/bin:/usr/bin

_ENV["runlevel"]3

_ENV["RUNLEVEL"]3

_ENV["PWD"]/

_ENV["LANG"]C

_ENV["previous"]N

_ENV["PREVLEVEL"]N

_ENV["SHLVL"]3

_ENV["HOME"]/

_ENV["_"]/usr/sbin/httpd

Il n'y a aucune différence en ce qui concerne le safe_mode.

Vois-tu, dans ces quelques lignes, ce expliquerait pourquoi sendmail plante lorsqu'il est lancé par le cron ?

De surcroît, il fait planter tout le serveur car le numproc / mémoire atteint les limites fixées par l'hébergeur.

Bonne journée.

Renaud.

Lien vers le commentaire
Partager sur d’autres sites

Posté (modifié)

Allo ? Personne n'a une idée ?

Pkoi cette page envoie les emails correctement avec Sendmail et phpMailer...et pas le cron ?

Après un test aujourd'hui, le cron a fait passer le VPS en "black zone" avec un numproc à 128 - maxi fixé par l'hébergeur.

Que puis-je faire ? envoyer avec mail au lieu de sendmail ? SMTP ?

Par ailleurs, si quelqu'un connaît bien phpMailer : on dirait qu'une fonction de la classe teste la validité des emails avant envoi,

car même si debug est à false, des messages type invalid adress toto_AT_free.fr s'affichent sur la page lors du passage de la boucle qui envoie. Et j'aimerais vraiment désactiver cette fonction car je traite les bounces autrement.

Une idée ?

Modifié par renaud63
Lien vers le commentaire
Partager sur d’autres sites

Moi je comprends plus grand chose... Tu es root, mais ton hébergeur te fixe des limites? C'est quoi comme hébergement? Pour moi il n'y a des limites que sur un mutualisé, et si tu es root, tu es forcément soit sur un dédié soit sur un virtuel, et ça devrait être pareil: pas de limites.

Ensuite, comment est-ce-que tu mets ton processus en cron? Comme déjà dit, la bonne idée c'est de le mettre dans le crontab d'un utilisateur lambda via crontab -e, plutôt que dans le crontab système.

Aussi, tu n'as pas dit si le script exécuté directement en ligne de commande (avec le même utilisateur que celui utilisé pour le cron) fonctionne ou pas.

Jacques.

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

Alors j'ai dû bien mal m'expliquer. Je reprends donc :

Je suis sur un VPS - dédié et pas privé - et oui j'ai l'accès root. Cette formule est je pense, à mi-chemin entre un mutu et un privé.

Donc il y a des limites quand même, notamment le nombre de processus qui peuvent tourner en même temps (numproc). Ici, c'est 128. Il y a, dans le virtuozzo, une rubrique "alertes QoS" qui montre zone verte, jaune, rouge ou noire (plantage total et redémarrage auto) pour : numproc, numfile et numothersock. Il semblerait que l'exécution du script de sendmail / phpMailer fasse voler ces limites et plante tout.

Il n'y a qu'un site / domaine sur ce serveur. J'ai vérifié le script d'envoi qui appelle phpMailer : pas de boucle sans fin ou autres, à peine une requête SQL avec une paire de LEFT OUTER JOIN, mais bon... appelé à la main dans le navigateur, le script envoie 2000 mails en 4mn...

Pour ce qui est du cron : oui, il est défini, via plesk, dans le domaine concerné avec le user de ce domaine, et pas au niveau du système lui même. Je ne sais pas utiliser crontab -e.

Lorsque je fais dans la console putty les tests que tu m'as demandés, alors oui, je me logue en root.

Ce matin, j'ai tenté de me loguer avec le user / passe du domaine pour exécuter la commande cron du script incriminé : je me fais jeter et putty ferme à la vitesse de la lumière. J'ai pu lui arracher un log : "Connection closed by remote host". Là s'arrêtent mes compétences.

Par contre : je me suis aperçu que des crontabs système (avec le user root) étaient programmés par défaut à une fréquence rapide. Et que les plantages de black zone numproc étaient peut-être liés à ces crons conjugués avec celui du domaine qui déclenche le sendmail. Car ces crons système semblent aussi être en rapport avec sendmail. Les voici :


12,22,32,42,52 * * * * /usr/lib64/plesk-9.0/postfix-poplockdb-clean
7,22,37,52 * * * * /usr/local/psa/admin/sbin/backupmng >/dev/null 2>&1

Apparemment, le premier serait lié à une table BDD de postfix et le second à un backup. Mais je peux me tromper, vu que je pipe que dalle à Linux.

Voila où j'en suis, c'est à dire à peu près nulle part. Et s'il te reste un peu de temps à me consacrer, et bien ce n'est pas de refus.

D'avance merci.

Renaud.

Lien vers le commentaire
Partager sur d’autres sites

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...