AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 767897
Accepted
user598527
user598527
Asked: 2024-01-28 18:53:52 +0800 CST2024-01-28 18:53:52 +0800 CST 2024-01-28 18:53:52 +0800 CST

Bash 经常无法将标准输出重定向到文件(来自 cat)

  • 772

我通常使用以下方法附加到文本文件cat:

cat >> FILE

我使用别名来避免意外覆盖文件(使用单个>):

alias a='cat >>'

Enter 更改行,Ctrl+D终止命令。我在主文件夹中写入多个文本文件,所有这些文件都是我创建、拥有并可以编辑的。

有几次,在我的桌面 Linux 系统 (Fedora 39) 和 Termux (Android) 上,命令停止重定向到文件,同时看似正常地接受输入。我丢失了数百行,主要是我粘贴的 URL。似乎仅在命令运行一段时间后才会发生。

是否有任何原因导致重定向cat >>可能停止运行?例如,任何特殊字符(在输入中)是否会产生影响?

更新:我已经确认各个文件的 inode 号不断变化($ ls -li或者查看确切时间$ stat -c '%w')——这是因为 Syncthing by design 重新创建了同步文件。我将来必须重新评估我如何使用该软件。抱歉一开始没有提到 Syncthing。

在我自动化的命令中,至少sed -i(就地编辑文件)也替换了索引节点。

该命令cat >> FILE也需要更换(已给出建议,请参阅评论和答案)。

bash
  • 2 2 个回答
  • 205 Views

2 个回答

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2024-01-28T19:35:50+08:002024-01-28T19:35:50+08:00

    运行后cat >> file,shell 将在fd 1 上的子进程中的file当前工作目录中打开,如果成功则在该进程中执行。O_WRONLY|O_CREAT|O_APPENDcat

    如果没有,shell 将输出错误消息并且不运行cat。

    如果找不到cat命令,它也会输出一条错误消息。

    cat依次,在循环中读取其 fd 0 并将其读取的内容写入 fd 1。

    同样,如果失败,它将输出一条错误消息。

    如果正在运行的进程cat被信号杀死或挂起,shell 还应该在 stderr 上报告它(例如,如果使用 SIGTTIN 挂起,则超过文件大小限制;如果使用 SIGTTIN挂起,则挂起(tty 输入))。SIGXFSZ

    如果 fd 0 在 tty 设备上打开,并且该 tty 设备是相同的,则 shell 从中读取其命令,通常是这种情况,在运行之前cat,shell 将按照进入其自己的行编辑器之前的方式配置 tty 的行规则。

    一般来说,这意味着它将处于icanon行规则实现粗略行编辑器的模式。

    在所有这些中,行编辑器实际上是唯一能够识别特殊字符的东西。stty -a会给你一个清单。就我而言:

    $ stty -a
    speed 38400 baud; rows 43; columns 159; line = 0;
    intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
    werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
    -parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
    -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel iutf8
    opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
    isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
    

    你会看到icanon上面提到的。^C, ^\, ^?, ^U, ^D, ^Q, ^S, ^Z, ^R, ^W, ^V,^O字符经过特殊处理。^C//受制于(在我的情况下已启用),^Z/受制于,(上面)在 Linux 上不受支持。^\isig^S^Qixondiscard^O

    例如,如果您输入foobar^Ubaz, 就会foobar被终止,但话又说回来,您会看到它在您键入的回显中被删除。

    输入^C角色会cat在其中间杀死read。

    但现在大多数终端模拟器在粘贴时都会删除这些字符。因此,为了在粘贴时发生这种情况,您需要使用一个仍然不执行剥离操作的终端,或者将其中一些kill/ werase/ intr... 设置设置为一些非控制字符,这将是病理状况。

    该行编辑器对其可以编辑的行的大小也有限制。在 Linux 上,IIRC 为 4095 字节。因此,如果您粘贴的行大于此值,则超过第 4095个字节的任何内容都将被丢弃。

    在该icanon模式下,当 tty 行编辑器退出时,cat's将返回,当您输入(它通过 on 转换为on )或或 或任何,或字符时,就会发生这种情况。read()^M^Jicrnl^Jeoleol2eof

    但无论如何,如果cat正常退出,也就是说,如果它没有被 SIGINT on^C或 SIGQUIT on杀死^\,或者没有被 SIGTSTP on 挂起^Z,并且没有报告错误,那么它将从终端读取输入并将其写入文件。

    因此,总而言之,您正在尝试的事情在正常情况下不应该发生,我能想到的唯一情况是病理情况:

    • 所报告的 tty 设置stty -a全部被窃听。
    • 或者您粘贴的数据包含由 tty 驱动程序的行编辑器解释的控制字符,并且由于某种原因您的终端编辑器不会删除它们。

    不要忽视人为错误,例如未能看到catshell 报告的错误或在与您想象的不同的目录中创建的文件,或者在cat运行时删除、替换、重命名或截断(就像您提到的使用Syncthing一样)在评论中)。

    使用该a='cat >>'别名,如果您输入a some file而不是a 'some file',则它cat >> some file与 相同,cat file >> some并且cat将读取file而不是 stdin 并将输出写入some而不是some file。

    对该别名的可能改进(假设 GNU tee)是:

    a() {
      rlwrap -pblue -S 'add> ' tee --output-error=warn -a -- "$@" > /dev/null
    }
    

    Whererlwrap为您提供了比原始 tty 驱动程序更高级的行编辑器(如果用作 shell,您已经熟悉了bash),并且有一个提示,可以更清楚地表明它正在等待一些输入。

    并且使用tee允许您一次将输入写入多个文件。

    • 5
  2. Chris Davies
    2024-02-09T03:53:05+08:002024-02-09T03:53:05+08:00

    如果目的是避免意外覆盖文件,请考虑设置适当的 shell 变量。例如,对于bash,

    set -o noclobber    # Do not allow > to overwrite a file
    set -C              # The same
    

    例子

    set -o noclobber
    echo >ddd
    echo >ddd
    -bash: ddd: cannot overwrite existing file
    
    set +o noclobber
    echo >ddd
    
    • 3

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve