我正在开发一个定期调用后台进程的应用程序。其中一个被 cron 调用,但我正在寻找更强大的东西,所以我将它转换为在 Supervisor 下运行。 (它可能会运行 10 分钟,在此期间它可以检测要执行的工作或空闲状态。一旦退出,Supervisor 将自动重新生成一个干净的实例。)
由于 Supervisor 更擅长确保只有指定数量的实例并行运行,我可以让它们运行更长时间。然而,这确实意味着我的进程更有可能接收到终止信号,要么是直接来自 kill,要么是因为它们已通过 Supervisor 停止。因此,我正在试验如何在 PHP 中处理此问题。
看起来基本的解决方案是使用 pcntl_signal()像这样:
declare(ticks = 1);
pcntl_signal(SIGTERM, 'signalHandler');
pcntl_signal(SIGINT, 'signalHandler');
function signalHandler($signal) {
switch($signal) {
case SIGTERM:
case SIGINT:
echo "Exiting now...\n";
exit();
}
}
但是,我的代码中有几点可以通过谨慎的关机处理来完成。一种方法是让一个处理程序调用这些不同的东西,但它需要一些重构,我想避免这种重构。另一种方法是在我需要的任何地方添加 pcntl_signal(),但不幸的是,一次似乎只能安装一个处理程序。
但是,看起来我可能能够使用register_shutdown_function() .这不会自行捕获 ^C 或其他终止信号,手册在这一点上非常清楚:
Shutdown functions will not be executed if the process is killed with a SIGTERM or SIGKILL signal
令人惊讶的是,我发现如果我使用 pcntl_signal() 来执行退出,那么确实会调用关闭处理程序。此外,由于一个人可以有多个关闭处理程序,这很好地解决了我的问题 - 我的代码中希望优雅地处理终止的每个类都可以捕获和管理自己的关闭。
我最初的问题是,为什么这样做有效?我试过在没有信号处理程序的情况下注册一个关闭函数,这似乎没有被调用,正如手册所说。我猜 PHP 会保持该进程存活以处理信号,这会导致调用关闭处理程序?
此外,当手册对它产生怀疑时,我可以依赖这种行为吗?我正在使用 PHP 5.5,目前还不想升级到 PHP7。所以我很想知道这是否适用于 5.5 和 5.6,以及各种发行版。
当然,它是否会(或不会)在 7.0 和/或 7.1 上工作也很有趣 - 我知道 ticks will be handled differently在 7.1 中,因此更有可能出现不同的行为。
最佳答案
PHP 用户关闭函数在普通进程终止期间被调用,有点类似于在其他编程语言中使用 atexit 注册的函数。显式 exit 或脚本末尾的隐式退出是普通进程终止。
然而,信号死亡是非正常的进程终止。 SIGTERM 的默认行为(以及 SIGKILL 的强制行为)是立即终止正在运行的进程,而不运行任何清理处理程序。
当您使用 pcntl_signal 拦截 SIGTERM 时,您正在安装不同的行为并让您自己有机会体验普通的进程终止。
是的,您可以依赖这种行为。虽然主要的手册条目并不明确,但您引用的“注释”的其余部分如下:
[Y]ou can use
pcntl_signal()to install a handler for a SIGTERM which usesexit()to end cleanly.
关于php - 如果设置了 pcntl_signal(),我可以依赖在 SIGTERM 上调用的 register_shutdown_function() 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38419471/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:
Foo=Class.newFoo.instance_evaldodefinstance_bar"instance_bar"endendputsFoo.instance_bar#=>"instance_bar"putsFoo.new.instance_bar#=>undefinedmethod‘instance_bar’我的理解是调用instance_eval在对象上应该允许您为该对象定义实例变量或方法。但是在上面的例子中,当你在类Foo上调用它来定义instance_bar方法时,instance_bar变成了一个可以用“Foo.instance_bar”调用的类方法。很明显这段代码没
假设我有一段Ruby代码,我想在其中为一个方法设置别名(我不知道为什么;让我们假设我有一个很好的理由)。classStringalias_method:contains?,:include?end我可以在本节之后删除这个别名吗? 最佳答案 remove_method在大多数情况下应该有效。但是,如果您的alias_method覆盖了现有方法,您可能需要通过单独的alias_method调用来保存原始方法。#assuming:contains?isalreadyamethodalias_method:original_contains
我喜欢RVM。我意识到它的主要用例是让不同的用户在不同版本的Ruby之间切换。但是假设我正在将Rails应用程序部署到服务器,并且我只想运行单个版本的Ruby。特别是,我想要1.9.2,用RVM安装它很容易,但没有它就很痛苦。有没有一种方法可以让我说“我希望这是所有用户的规范Ruby安装”(连同它的所有gem),而不必手动创建一堆符号链接(symboliclink)并在每次更新到更新时更改它们Ruby版本? 最佳答案 以root身份安装RVM并执行sudorvmuse1.9.2--default。任何采购/usr/local/rvm
date_select方法只能设置:start_year,但我想设置开始日期(例如3个月前的日期)(但没有这样的选项)。那么,我可以将开始日期设置为date_select方法吗?或者,要制作这样的选择框,我应该使用select_tag和options_for_select吗?或者,有什么解决办法吗?谢谢, 最佳答案 有可能……例如:start_year–设置年份选择的开始年份。默认为Time.now.year-5参见thisresource. 关于ruby-Rails3-我可以将开始日期
所以我正在研究RubyKoans,而且我遇到了一个我认为是ruby1.9.x特有的问题。deftest_calling_global_methods_without_parenthesesresult=my_global_method2,3assert_equal5,resultend我明白了:james@tristan:~/code/ruby_projects/ruby_koans$rake(in/home/james/code/ruby_projects/ruby_koans)cdkoans/home/james/.rvm/rubies/ruby-1.9.2-p180/bin/ru
希望我没有误解“ducktyping”的含义,但从我读到的内容来看,这意味着我应该根据对象如何响应方法而不是它是什么类型/类来编写代码。代码如下:defconvert_hash(hash)ifhash.keys.all?{|k|k.is_a?(Integer)}returnhashelsifhash.keys.all?{|k|k.is_a?(Property)}new_hash={}hash.each_pair{|k,v|new_hash[k.id]=v}returnnew_hashelseraise"CustomattributekeysshouldbeID'sorPropertyo