Cron 作业未在所有站点上激活
Posted
技术标签:
【中文标题】Cron 作业未在所有站点上激活【英文标题】:Cron Job not activating on all sites 【发布时间】:2015-06-09 00:56:16 【问题描述】:我有一些需要通过 Cron 访问的网站。我不想创建 20 个 cron 作业,所以我创建了一个在我的开发服务器上命中单个 php 脚本的作业。它看起来像这样:
<?php //This script will send out directives to send [some] emails to [people]
//Start new init with $ch1, $ch2, $ch3 etc
$ch1 = curl_init();
$ch2 = curl_init();
$ch3 = curl_init();
$ch4 = curl_init();
$ch5 = curl_init();
$ch6 = curl_init();
$ch7 = curl_init();
$ch8 = curl_init();
$ch9 = curl_init();
$ch10 = curl_init();
$ch11 = curl_init();
$ch12 = curl_init();
$ch13 = curl_init();
$ch14 = curl_init();
$ch15 = curl_init();
$ch16 = curl_init();
$ch17 = curl_init();
$ch18 = curl_init();
$ch19 = curl_init();
//Set URL and options
curl_setopt($ch1, CURLOPT_URL, 'http://site1.com/?key=mykey');
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch2, CURLOPT_URL, 'http://site2.com/?key=mykey');
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch3, CURLOPT_URL, 'http://site3.com/?key=mykey');
curl_setopt($ch3, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch4, CURLOPT_URL, 'http://site4.com/?key=mykey');
curl_setopt($ch4, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch5, CURLOPT_URL, 'http://site5.com/?key=mykey');
curl_setopt($ch5, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch6, CURLOPT_URL, 'http://site6.com/?key=mykey');
curl_setopt($ch6, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch7, CURLOPT_URL, 'http://site7.com/?key=mykey');
curl_setopt($ch7, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch8, CURLOPT_URL, 'http://site8.com/?key=mykey');
curl_setopt($ch8, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch9, CURLOPT_URL, 'http://site9.com/?key=mykey');
curl_setopt($ch9, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch10, CURLOPT_URL, 'http://site10.com/?key=mykey');
curl_setopt($ch10, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch11, CURLOPT_URL, 'http://site11.com/?key=mykey');
curl_setopt($ch11, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch12, CURLOPT_URL, 'http://site12.com/?key=mykey');
curl_setopt($ch12, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch13, CURLOPT_URL, 'http://site13.com/?key=mykey');
curl_setopt($ch13, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch14, CURLOPT_URL, 'http://site14.com/?key=mykey');
curl_setopt($ch14, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch15, CURLOPT_URL, 'http://site15.com/?key=mykey');
curl_setopt($ch15, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch16, CURLOPT_URL, 'http://site16.com/?key=mykey');
curl_setopt($ch16, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch17, CURLOPT_URL, 'http://site17.com/?key=mykey');
curl_setopt($ch17, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch18, CURLOPT_URL, 'http://site18.com/?key=mykey');
curl_setopt($ch18, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch19, CURLOPT_URL, 'http://site19.com/?key=mykey');
curl_setopt($ch19, CURLOPT_RETURNTRANSFER, 1);
//Create multiple cURL handlers
$mh = curl_multi_init();
//Add the handles
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);
curl_multi_add_handle($mh, $ch3);
curl_multi_add_handle($mh, $ch4);
curl_multi_add_handle($mh, $ch5);
curl_multi_add_handle($mh, $ch6);
curl_multi_add_handle($mh, $ch7);
curl_multi_add_handle($mh, $ch8);
curl_multi_add_handle($mh, $ch9);
curl_multi_add_handle($mh, $ch10);
curl_multi_add_handle($mh, $ch11);
curl_multi_add_handle($mh, $ch12);
curl_multi_add_handle($mh, $ch13);
curl_multi_add_handle($mh, $ch14);
curl_multi_add_handle($mh, $ch15);
curl_multi_add_handle($mh, $ch16);
curl_multi_add_handle($mh, $ch17);
curl_multi_add_handle($mh, $ch18);
curl_multi_add_handle($mh, $ch19);
$active = null;
//Execute handles
do
$mrc = curl_multi_exec($mh, $active);
while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK)
if (curl_multi_select($mh) != -1)
do
$mrc = curl_multi_exec($mh, $active);
while ($mrc == CURLM_CALL_MULTI_PERFORM);
//Error Report
echo 'Errors for <strong>site1.com</strong>: '.curl_error($ch1).'<br />';
echo 'Error Count for site1.com: <strong>'.curl_errno($ch1).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site2.com</strong>: '.curl_error($ch2).'<br />';
echo 'Error Count for site2.com: <strong>'.curl_errno($ch2).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site3.com</strong>: '.curl_error($ch3).'<br />';
echo 'Error Count for site3.com: <strong>'.curl_errno($ch3).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site4.com</strong>: '.curl_error($ch4).'<br />';
echo 'Error Count for site4.com: <strong>'.curl_errno($ch4).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site5.com</strong>: '.curl_error($ch5).'<br />';
echo 'Error Count for site5.com: <strong>'.curl_errno($ch5).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site6.com</strong>: '.curl_error($ch6).'<br />';
echo 'Error Count for site6.com: <strong>'.curl_errno($ch6).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site7.com</strong>: '.curl_error($ch7).'<br />';
echo 'Error Count for site7.com: <strong>'.curl_errno($ch7).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site8.com</strong>: '.curl_error($ch8).'<br />';
echo 'Error Count for site8.com: <strong>'.curl_errno($ch8).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site9.com</strong>: '.curl_error($ch9).'<br />';
echo 'Error Count for site9.com: <strong>'.curl_errno($ch9).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site10.com</strong>: '.curl_error($ch10).'<br />';
echo 'Error Count for site10.com: <strong>'.curl_errno($ch10).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site11.com</strong>: '.curl_error($ch11).'<br />';
echo 'Error Count for site11.com: <strong>'.curl_errno($ch11).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site12.com.au</strong>: '.curl_error($ch12).'<br />';
echo 'Error Count for site12.com.au: <strong>'.curl_errno($ch12).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site13.com</strong>: '.curl_error($ch13).'<br />';
echo 'Error Count for site13.com: <strong>'.curl_errno($ch13).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site14.com</strong>: '.curl_error($ch14).'<br />';
echo 'Error Count for site14.com: <strong>'.curl_errno($ch14).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site15.com</strong>: '.curl_error($ch15).'<br />';
echo 'Error Count for site15.com: <strong>'.curl_errno($ch15).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site16.com</strong>: '.curl_error($ch16).'<br />';
echo 'Error Count for site16.com: <strong>'.curl_errno($ch16).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site17.com</strong>: '.curl_error($ch17).'<br />';
echo 'Error Count for site17.com: <strong>'.curl_errno($ch17).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site18.com</strong>: '.curl_error($ch18).'<br />';
echo 'Error Count for site18.com: <strong>'.curl_errno($ch18).'</strong><br /><br />';
echo '<hr />';
echo 'Errors for <strong>site19.com</strong>: '.curl_error($ch19).'<br />';
echo 'Error Count for site19.com: <strong>'.curl_errno($ch19).'</strong><br /><br />';
//Close handles
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_remove_handle($mh, $ch3);
curl_multi_remove_handle($mh, $ch4);
curl_multi_remove_handle($mh, $ch5);
curl_multi_remove_handle($mh, $ch6);
curl_multi_remove_handle($mh, $ch7);
curl_multi_remove_handle($mh, $ch8);
curl_multi_remove_handle($mh, $ch9);
curl_multi_remove_handle($mh, $ch10);
curl_multi_remove_handle($mh, $ch11);
curl_multi_remove_handle($mh, $ch12);
curl_multi_remove_handle($mh, $ch13);
curl_multi_remove_handle($mh, $ch14);
curl_multi_remove_handle($mh, $ch15);
curl_multi_remove_handle($mh, $ch16);
curl_multi_remove_handle($mh, $ch17);
curl_multi_remove_handle($mh, $ch18);
curl_multi_remove_handle($mh, $ch19);
curl_multi_close($mh);
echo 'Script Executed Successfully!'; // Just shows me the file is actually loading to completion
?>
这些网站中的每一个都是为处理查询字符串而构建的 WordPress。
<?php
if( $_GET['key'] == 'mykey')
$network_array = wp_get_sites();
foreach( $network_array as $site )
$temp = file_get_contents('http://'.$site['domain'].'/page-with-mail-script/?runkey=AnotherKey');
$temp = '';
?>
此时,想法是使用wp_get_sites()
函数来获取该特定网络上所有站点的数组(这些都是wordpress 多站点)。我使用file_get_contents()
访问带有查询字符串的站点以在该页面上运行脚本。
该页面模板使用 MailChimp 的 Mandrill 为要发送的电子邮件列表运行 wp_query,并为要发送的“联系人”列表运行 wp_query。这是那个文件:
get_header();
do_action( 'genesis_before_content_sidebar_wrap' );
?>
<div id="content-sidebar-wrap">
<?php do_action( 'genesis_before_content' ); ?>
<div id="content" class="hfeed">
<?php
if($_GET['key'] == 'AnotherKey')
#Start up contact query
$contact_query = new WP_Query(array('post_type' => 'contacts', 'posts_per_page' => '-1'));
$invite_query = new WP_Query(array('post_type' => 'invites', 'posts_per_page' => '-1'));
#Let's use the get_posts method for a foreach loop option
$contacts = $contact_query->get_posts();
$invites = $invite_query->get_posts();
#Loop through the contacts
foreach( $contacts as $contact )
$email_status = 'skipped.';
#Initiate the custom fields
$contact_custom = get_post_custom($contact->ID);
#Return custom fields as variables
$email_address = $contact_custom['email_address'][0]; //Where do we reach them?
$email_number = $contact_custom['email_number'][0]; //Which email do they need?
$last_email_date = $contact_custom['last_email_date'][0]; //When did they last get one?
//$phone_number = $contact_custom['phone_number']; // Phone Number (NOT USED 9-23-14)
#Let's get some other variables we need
$today = time();
$remove_me_link = '<a href="'.site_url().'/remove-me?email='.urlencode($email_address).'" target="_blank">Get Removed From This List</a>';
#If EMAIL_NUMBER is GREATER than zero, continue, otherwise skip (this is set to a negative value to remove them from the list)
if( $email_number > 0 )
#We need to find the email to send them.
foreach( $invites as $invite )
#Initiate the custom fields
$invite_custom = get_post_custom($invite->ID);
#Return custom fields as variables
$invite_number = $invite_custom['invite_number'][0]; //Which email is this?
$invite_delay = $invite_custom['invite_delay'][0]; //How long should we wait to send this one?
$forgiving_delay = $invite_delay * 86400; //Ex. 1, or 7 times a unix day
$forgiving_delay = $forgiving_delay - 28800; // Remove 8 hours from the timeframe, this allows some leway in server time discrepancies
$publish_date = get_the_time('U', $contact->ID); //Convert publish date to unix
#See if the invite number matches their required email number
if( $invite_number == $email_number )
#It does! Now see if the proper delay has been met
if( empty($last_email_date) || $last_email_date == '' || $last_email_date < 9999 ) //This means they're new. We need to wait until the delay after the PUBLISH date for this.
if($today - $publish_date > $forgiving_delay)
$to = $email_address;
$subject = $invite->post_title;
$message = '
<html>
<head>
<title>'.$invite->post_title.'</title>
</head>
<body>
<p>'.$invite->post_content.'</p>
<br />
<br />
<p style="font-size: 10px;">This email was sent to you on behalf of <strong>'.$gv->organization.'</strong>, <strong>'.$gv->address.', '.$gv->city.' '.$gv->state.' '.$gv->zip_code.'</strong><br />If you have any questions, please send an email to <strong>'.$gv->author_email.'</strong> or call <strong>'.$gv->phone.'</strong>.</p>
<p style="font-size: 10px;">Don\'t want to see this? '.$remove_me_link.'</p>
</body>
</html>';
$message = str_replace('contact_name', $contact->post_title, $message);
$message = str_replace('contact_email', $email_address, $message);
$message = str_replace('review_engine_url', str_replace(array('http://', 'https://'), '', site_url()), $message);
$message = str_replace('google_url', $gv->google_plus, $message);
$message = str_replace('yelp_url', $gv->yelp, $message);
$message = str_replace('facebook_url', $gv->like_box, $message);
$message = str_replace('review_site_one_url', $gv->review_site_one_url, $message);
$message = str_replace('review_site_two_url', $gv->review_site_two_url, $message);
$message = str_replace('review_site_three_url', $gv->review_site_three_url, $message);
$message = str_replace('review_site_four_url', $gv->review_site_four_url, $message);
$message = str_replace('superpages_url', $gv->super_pages, $message);
$message = nl2br($message);
//$from = 'mailer@'.str_replace(array('http://', 'https://'), '', site_url());
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
//$headers .= 'From: '.$from;
$mail = wpMandrill::mail($to, $subject, $message, $headers);
#If it succeeded, let's update post data in the contact
if( $mail )
update_post_meta($contact->ID, 'email_number', $email_number + 1);
update_post_meta($contact->ID, 'last_email_date', $today);
$email_status = 'Good!';
else
$email_status = 'Bad.';
echo $contact->post_title.': <strong>'.$email_status.'</strong><br />';
else
if($today - $last_email_date > $forgiving_delay) // This means they've gotten emails before, proceed as normal
//trm_send_invite_email(); //WHAT DID THIS DO?
$to = $email_address;
$subject = $invite->post_title;
$message = '
<html>
<head>
<title>'.$invite->post_title.'</title>
</head>
<body>
<p>'.$invite->post_content.'</p>
<br />
<br />
<p style="font-size: 10px;">This email was sent to you on behalf of <strong>'.$gv->organization.'</strong>: <strong>'.$gv->address.', '.$gv->city.' '.$gv->state.' '.$gv->zip_code.'</strong><br />If you have any questions, please send an email to <strong>'.$gv->author_email.'</strong> or call <strong>'.$gv->phone.'</strong>.</p>
<p style="font-size: 10px;">Don\'t want to see this? '.$remove_me_link.'</p>
</body>
</html>';
$message = str_replace('contact_name', $contact->post_title, $message);
$message = str_replace('contact_email', $email_address, $message);
$message = str_replace('review_engine_url', str_replace(array('http://', 'https://'), '', site_url()), $message);
$message = str_replace('google_url', $gv->google_plus, $message);
$message = str_replace('yelp_url', $gv->yelp, $message);
$message = str_replace('facebook_url', $gv->like_box, $message);
$message = str_replace('review_site_one_url', $gv->review_site_one_url, $message);
$message = str_replace('review_site_two_url', $gv->review_site_two_url, $message);
$message = str_replace('review_site_three_url', $gv->review_site_three_url, $message);
$message = str_replace('review_site_four_url', $gv->review_site_four_url, $message);
$message = str_replace('superpages_url', $gv->super_pages, $message);
$message = nl2br($message);
//$from = $gv->organization.'@'.str_replace(array('http://', 'http:s//'), '', site_url());
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
//$headers .= 'From: '.$from;
$mail = wpMandrill::mail($to, $subject, $message, $headers);
#If it succeeded, let's update post data in the contact
if( $mail )
update_post_meta($contact->ID, 'email_number', $email_number + 1);
update_post_meta($contact->ID, 'last_email_date', $today);
else
$email_status = 'Bad.';
echo $contact->post_title.': <strong>'.$email_status.'</strong><br />';
//End Invite Loop
//End Contact loop
else
echo '<h1 class="entry-title">Hold on, partner!</h1>';
echo '<p>You\'re not supposed to be here!</p>';
?>
</div><!-- end #content -->
<?php do_action( 'genesis_after_content' ); ?>
<div style="clear:both;"></div>
</div><!-- end #content-sidebar-wrap -->
<?php
do_action( 'genesis_after_content_sidebar_wrap' );
get_footer();
我收到来自 Cron 守护程序的通知,说脚本已执行,通过在第一个被 cron 命中的文件中显示“脚本已成功执行”回显。
问题是,电子邮件似乎是在前几个网站上发送的,但随后其余部分保持不变,如“联系人”帖子类型中的自定义字段所示。
脚本是否超时?被杀?我应该不是在一个文件中访问每个站点,而是分别访问每个站点?还是我应该使用curl_init()
、curl_setopt
,然后在转到下一个之前删除cURL?
【问题讨论】:
检查您的邮件服务器日志怎么样? 我们使用 Mandrill - 那里还会出现吗? 不熟悉 Mandril,很遗憾。寻找一些错误日志或什么?你可以看看这个:***.com/questions/21456680/… 并搜索你的积压工作在哪里:) 你可能需要array('http://', 'https://')
,而不是array('http://', 'http:s//')
。
【参考方案1】:
我们试图做几乎完全相同的事情,(Wordpress 多站点电子邮件)并遇到了内置 PHPMailer 类的超时问题(wp_mail() 函数是它的包装器)。我的 CRON 脚本总是会收到 100 封电子邮件,然后就死掉了。该脚本会回显它已完成发送,但我只会收到前 100 封。有趣的是,当我在同一服务器上的两个 Wordpress 站点之间拆分它时,我会在每个站点上收到 50 封电子邮件。我不熟悉 Mandrill,但我想知道您是否遇到了速率限制,在太短的时间内启动了太多的电子邮件发送。
这是两次执行mail()函数吗?
也许改变这个:
$mail = wpMandrill::mail($to, $subject, $message, $headers);
#If it succeeded, let's update post data in the contact
if( $mail )
update_post_meta($contact->ID, 'email_number', $email_number + 1);
到这里:
if( $mail = wpMandrill::mail($to, $subject, $message, $headers) )
update_post_meta($contact->ID, 'email_number', $email_number + 1);
【讨论】:
哦,你是对的!我已经交换了那个代码。至于速率限制,情况并非如此(可能是一个,但不是这种情况)。我知道这是因为如果它在 100 次后关闭,如果我再次运行它,它会执行下一个 100 次,因为它的设计是在没有安排发送电子邮件的情况下跳过。我已经在一个更大的网站上运行了很多次(很多网站根本没有使用 trhe 功能,到目前为止大多数网站都有 5-12 封电子邮件):/【参考方案2】:为什么要为此打开 19 个单独的连接处理程序?我不知道这是否会导致您描述的问题,但它肯定不会有帮助。
【讨论】:
以上是关于Cron 作业未在所有站点上激活的主要内容,如果未能解决你的问题,请参考以下文章
cron 工作正在 magento 站点工作-但没有找到心跳