Обработка перенаправлений обычно выполняется после разветвления подпроцесса, но обязательно выполняется до с использованием execve()
для передачи управления из оболочки в новый исполняемый файл (в вашем случаеcurl
или wget
) выполняется в этом процессе.
Поскольку вы уже fork()
'd, изменения в переменных происходят в контексте нового процесса и не передаются обратно вparent.
Это не относится к стандартному echo
, поскольку он встроен в оболочку и, следовательно, находится в процессе (вообще не требует fork
), но не делает применяется к /bin/echo
для оболочек, реализованных таким образом (что стандарт POSIX не запрещает и не требует).
Более простой способ воспроизведения этой проблемы - показывает, что он применяется к all не встроенные команды - следует, как сгенерировано с помощью bash 3.2.57, а также воспроизведено для 4.4.23:
$ i=0; echo >>"test$((++i)).tmp"; echo "$i"
1
$ i=0; /bin/echo >>"test$((++i)).tmp"; echo "$i"
0
Если вы хотите обойти эту проблему, вы можете сделатьтак, выполнив перенаправлениеn для всей группы команд:
$ i=0; { /bin/echo; } >>"test$((++i)).tmp"; echo "$i"
1
Конструкция { ...; }
выполняет перенаправление для всего блока команд и, таким образом, выполняет перенаправление до того, как разветвляется от дочернего процесса, который будетзаменено на /bin/echo
.