bash&中的重定向顺序同时覆盖和追加

时间:2014-11-27 00:39:33

标签: bash redirect file-descriptor

首先,我们有一些命令:

service --status-all 1>one 2>one
service --status-all 1>two 2>>two
service --status-all 1>>three 2>>three
service --status-all 1>>four 2>four

service --status-all 2>one1 1>one1
service --status-all 2>two1 1>>two1
service --status-all 2>>three1 1>>three1
service --status-all 2>>four1 1>four1

执行后,以下内容相同:

three = three1 ,所以这些是相同的:

service --status-all 1>>three 2>>three
service --status-all 2>>three1 1>>three1

one = four = one1 = two1 ,所以这些是相同的:

service --status-all 1>one 2>one
service --status-all 1>>four 2>four
service --status-all 2>one1 1>one1
service --status-all 2>two1 1>>two1

两个= four1 ,所以这些是相同的:

service --status-all 1>two 2>>two
service --status-all 2>>four1 1>four1

文件内容:

文件一个 = 四个 = one1 = two1

 [ ? ]  apport
 [ ? ]  binfmt-support
 [ ? ]  console-setup
 [ ? ]  dns-clean
 [ ? ]  irqbalance
 [ ? ]  killprocs
 [ ? ]  kmod
 [ ? ]  lightdm
 [ ? ]  mysql
 [ ? ]  networking
 [ ? ]  ondemand
 [ ? ]  pppd-dns
 [ ? ]  rc.local
 [ ? ]  sendsigs
 [ ? ]  speech-dispatcher
 [ ? ]  umountfs
 [ ? ]  umountnfs.sh
 [ ? ]  umountroot
]  sudo
 [ - ]  udev
 [ - ]  unattended-upgrades
 [ - ]  urandom
 [ + ]  virtualbox
 [ - ]  x11-common

文件两个 = four1

 [ + ]  acpid
 [ - ]  anacron
 [ - ]  apparmor
 [ + ]  avahi-daemon
 [ + ]  bluetooth
 [ - ]  brltty
 [ + ]  cron
 [ + ]  cups
 [ + ]  cups-browsed
 [ - ]  dbus
 [ + ]  friendly-recovery
 [ - ]  grub-common
 [ + ]  kerneloops
 [ - ]  procps
 [ - ]  pulseaudio
 [ + ]  resolvconf
 [ - ]  rsync
 [ + ]  rsyslog
 [ + ]  saned
 [ - ]  sudo
 [ - ]  udev
 [ - ]  unattended-upgrades
 [ - ]  urandom
 [ + ]  virtualbox
 [ - ]  x11-common
nfs.sh
 [ ? ]  umountroot

文件 = three1

 [ + ]  acpid
 [ - ]  anacron
 [ - ]  apparmor
 [ ? ]  apport
 [ + ]  avahi-daemon
 [ ? ]  binfmt-support
 [ + ]  bluetooth
 [ - ]  brltty
 [ ? ]  console-setup
 [ + ]  cron
 [ + ]  cups
 [ + ]  cups-browsed
 [ - ]  dbus
 [ ? ]  dns-clean
 [ + ]  friendly-recovery
 [ - ]  grub-common
 [ ? ]  irqbalance
 [ + ]  kerneloops
 [ ? ]  killprocs
 [ ? ]  kmod
 [ ? ]  lightdm
 [ ? ]  mysql
 [ ? ]  networking
 [ ? ]  ondemand
 [ ? ]  pppd-dns
 [ - ]  procps
 [ - ]  pulseaudio
 [ ? ]  rc.local
 [ + ]  resolvconf
 [ - ]  rsync
 [ + ]  rsyslog
 [ + ]  saned
 [ ? ]  sendsigs
 [ ? ]  speech-dispatcher
 [ - ]  sudo
 [ - ]  udev
 [ ? ]  umountfs
 [ ? ]  umountnfs.sh
 [ ? ]  umountroot
 [ - ]  unattended-upgrades
 [ - ]  urandom
 [ + ]  virtualbox
 [ - ]  x11-common

有18个问号(stderr线)。 Stderr明显覆盖了前18行stdout,然后是一些(sudo line)。

为什么会出现这种行为?

我的操作系统是Ubuntu 14.04。

2 个答案:

答案 0 :(得分:1)

在每次写入之前,为自动附加而打开的流会自动将自身重新定位到文件末尾。如果另一个流在其两个写入之间写入文件,它将重新定位。

另一方面,为正常输出打开的流不会重新定位。如果附加流写入某些内容,然后普通流写入内容,则第二次写入将覆盖第一次写入的内容。

此外,如果程序使用stdio,则某些写入可能会被缓冲。刷新缓冲区时会发生上述行为,而不是在程序调用缓冲的写入函数时。默认情况下,stdout在写入文件时是完全缓冲的,stderr是无缓冲的。

答案 1 :(得分:0)

您实际看到的奇怪行为实际上与重定向顺序无关,而且与输出缓冲和传递给open()的标志有关。

您使用O_APPEND [正如>>所做的那样]打开您的一个文件 - 因此所有的写入将始终结束 - 而另一个写入>因此缺少保证。此外,正如您报告的行为所证明的那样,您的程序不会对其写入执行行缓冲,这意味着您的写入会被拆分为大块,这些块不能保证在行边界处结束并且这些块是散布的

如果您的程序执行了行缓冲写入,则可以使用>>作为两个文件描述符,并且事情通常会起作用(只要这些行足够短以便由单个write()完成呼叫)。但是,它没有,所以你不能以这种方式拆分和重新组合它的输出,并期望事物在线边界上分开。


现在,回答有关重定向顺序的字面问题(它与手头问题的实际原因没有任何关系):

严格地从左到右。