Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux “制造回声”;“福”sudo-tee-幂等元_Linux_Bash_Shell_Tee - Fatal编程技术网

Linux “制造回声”;“福”sudo-tee-幂等元

Linux “制造回声”;“福”sudo-tee-幂等元,linux,bash,shell,tee,Linux,Bash,Shell,Tee,我正在使用以下shell命令将字符串附加到文件: echo "latest stable main" | sudo tee -a /etc/my-app.conf > /dev/null 但是,这不是幂等的,也就是说,如果字符串已经存在于/etc/my app.conf中,则每次调用命令时都会多次追加该字符串。只有当它不存在于一个聪明的单行程序中时,才可能追加吗?简短的回答是:简单、容易和错误 如果您不关心角落案例(多行输入、并发调用等)中的正确性,那么以下几点可以完成这项工作: gre

我正在使用以下shell命令将字符串附加到文件:

echo "latest stable main" | sudo tee -a /etc/my-app.conf > /dev/null
但是,这不是幂等的,也就是说,如果字符串已经存在于
/etc/my app.conf
中,则每次调用命令时都会多次追加该字符串。只有当它不存在于一个聪明的单行程序中时,才可能追加吗?

简短的回答是:简单、容易和错误 如果您不关心角落案例(多行输入、并发调用等)中的正确性,那么以下几点可以完成这项工作:

grep -Fxe 'latest stable main' /etc/my-app.conf || {
  sudo tee -a /etc/my-app.conf <<<"latest stable main"
}

您还可以使用Ansible模块来确保文件中有特定的行。

grumble——寻找“聪明的一行代码”而不是寻找正确的解决方案是一条通向微妙错误代码的捷径,特别是在bash中(bash中充满了微妙的陷阱,需要避免的变通方法往往并不简洁)…也就是说--您需要担心的只是同一程序的其他实例(例如,允许使用合作/建议锁定方法),还是我们也关心与非合作编写器的互操作性?此外,此文件的长度是多少?我们是想把它读入内存,还是不应该假设它合适?如果您不关心正确处理并发性,或者不独立地评估每一行是否与现有内容重复,那么这可能只是
grep-e'latest stable main'yourfile | |……
。当然,尽管人们应该关心创建一个配置目录
/etc/my app.conf.d/
,然后只需触摸
/etc/my app.conf.d/latest
。让fs来处理它。如果它是一个编辑器提示,为什么两者都使用
/usr/bin/env
?编辑可能会对
#感到满意!bash
,因为解释器的路径不会影响语法突出显示。
#!/bin/bash
# ^^^- shebang present as an editor hint; this file should be sourced, not executed.

case $BASH_VERSION in ''|[0-3].*|4.0.*) echo "ERROR: Bash 4.1 or newer required" >&2; return 1 >/dev/null 2>&1; exit 1;; esac

appendEachNewLine() {
  local file=$1 line out_fd
  local -A existingContents=( )   # associative array, to track lines that already exist

  # dynamically assign a file descriptor on which to both lock our file and write
  exec {out_fd}>>"$file"
  flock -x -n "$out_fd" || {
    echo "ERROR: Unable to lock destination file" >&2
    exec {out_fd}>&-
    return 1
  }

  # read existing lines once, through a new file descriptor, only after holding the lock
  while IFS= read -r line; do
    existingContents[$line]=1
  done <"$file"

  # then process our stdin, appending each line if not previously seen
  while IFS= read -r line; do
    if ! [[ ${existingContents[$line]} ]]; then
      printf '%s\n' "$line" >&"$out_fd"
    fi
  done

  # close the file, thus releasing the lock, when done.
  exec {out_fd}>&-
}

appendEachNewLineAsRoot() {
  sudo bash -c "$(declare -f appendEachNewLine)"'; appendEachNewLine "$@"' appendEachNewLine "$@";
}
echo "latest stable main" | appendEachNewLineAsRoot /etc/my-app.conf