0%

cron 文件

hello-cron

1
2
* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file.

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM ubuntu:latest
MAINTAINER docker@ekito.fr

RUN apt-get update && apt-get -y install cron

# Copy hello-cron file to the cron.d directory
COPY hello-cron /etc/cron.d/hello-cron

# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron

# Apply cron job
RUN crontab /etc/cron.d/hello-cron

# Create the log file to be able to run tail
RUN touch /var/log/cron.log

# Run the command on container startup
CMD cron && tail -f /var/log/cron.log

测试

script
1
2
docker build --rm -t ekito/cron-example .
docker run -it ekito/cron-example

说明

可以使用 cron -f 作为 dockerfile 的 CMD,这样会强制 crontab 前台运行

原文地址:

how-to-run-a-cron-job-inside-a-docker-container

依赖

pcntl 扩展

源码

signal.php

1
2
3
4
5
6
7
8
9
10
11
12
<?php

declare(ticks=1);

pcntl_signal(SIGUSR1, function () {
file_put_contents('signal_test.log', time() . PHP_EOL, FILE_APPEND);
});

while (true) {
sleep(1);
}

运行

查看进程 ID

1
ps aux | grep signal.php | grep -v grep

发送信号

假设进程 ID 是 12345

1
kill -SIGUSR1 12345

用处

可以让我们不重启 php 进程的同时做一些处理。

比如,接收到信号后从磁盘读取新的配置文件等。

以往写法

在以往的 PHP 版本中,我们使用匿名函数的方式可能会显得非常冗长,即使里面只是一个简单的返回,或者一个简单的表达式。

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$students = [
[
'name' => 'Foo',
'age' => 20,
],
[
'name' => 'Bar',
'age' => 21,
],
];

$names = array_map(function ($student) {
return $student['name'];
}, $students);

写过 ES6 或者 Java8 的朋友应该对箭头函数这种写法比较熟悉,对比一下:

ES6

1
let names = students.map(student => student.name)

JAVA8 则类似下面的 map 那样

1
2
3
students.stream()
.map(student -> student.name)
.collect(Collectors.toList())

相对比之下,php 就显得有些啰嗦,如果闭包函数里面需要使用外部变量,则还需要把每一个外部变量写到 use 里面,那就会更加冗长。

箭头函数 hello world

现在我们使用箭头函数来重写一下上面的 array_map 调用:

1
2
$names = array_map(fn ($student) => $student['name'], $students);
var_dump($names);

在线运行以上代码: php74-playground

怎么样?是不是简洁又清晰,看起来特别舒服。 functionreturnuse 这些全都不用写了。

同时,如果需要使用外部的变量,再也不需要使用 use 来引入那些外部变量了,在箭头函数后面的表达式直接可以使用:

1
2
3
$y = 10;
$fn = fn ($x) => $x + $y;
var_dump($fn(20)); // 30

在线运行以上代码: php74-playground

旧的写法:

1
2
3
4
5
$y = 10;
$fn = function ($x) use ($y) {
return $x + $y;
};
var_dump($fn(20)); // 30

箭头函数写法

基本形式

1
fn (parameter_list) => expr

简单说一下(但是很重要):

  • fn 是箭头函数标识,原来的 function 关键字在箭头函数里只需写 fn
  • (parameter_list) 是箭头函数的参数列表,fn 和 括号不能省略
  • expr 这个名字已经说明了一切,这里我们只能写一个表达式,不能写多个语句,不接受语句块。
  • expr 是一个表达式,同时也是这个箭头函数的返回值,原来的 return 不用写了

有人会说,为什么还要写 fn,直接 parameter => expr 不就好了吗?

这是因为这种写法已经用于 PHP 的关联数组里面了,冲突了。

想了解为什么的可以看 rfc/arrow_functions_v2

函数签名

  • fn (array $x) => $x;,参数类型限定
  • fn (): int => $x;,返回值类型限定
  • fn ($x = 42) => $x;,参数默认值
  • fn (&$x) => $x;,参数引用传递
  • fn &($x) => $x;,返回值引用
  • fn ($x, ...$rest) => $rest;

总的来说:

参数传递、参数类型限定、返回值类型限定、引用参数传递、返回值引用等写法和旧的写法一致。

不一样的是:

  • 没有了 functionreturnuse 等关键字,也没有了大括号

  • 需要注意的是:不支持大括号,不像 ES6

    • 错误写法:fn (array $x) => {return $x;};

兼容性问题

  • 从 PHP 7.4 起,因为引入了 fn 关键字作为箭头函数的语法,因此,如果你的代码里面有 fn 命名的函数,可能会有冲突。

总结

  • 基本语法 fn (parameter_list) => expr

  • PHP7.4 的箭头函数只支持简单的表达式(只能写一个表达式),不能使用大括号把表达式括起来

想尝鲜的可以在 php74-playground 尝试一下!基于 PHP 7.4.0RC1 版本。