首先我不知道我是否在STDOUT之外谈论STDIN,但这是我想要实现的目标:
有一个程序可以从远程服务器导出数据库,并将输出作为压缩内容发送。
我想解压缩内容,然后解析。
如果可以,请导入它,否则发送错误消息。我不想写入磁盘上的任何临时文件,所以我想直接从STD处理事情
someExportCommand > /dev/stdin #seems not work
#I want to write a message here
echo "Export database done"
cat /dev/stdin > gunzip > /dev/stdin
echo "Unzip done"
if [[ "$mycontentReadFromSTDIN" =* "password error" ]]; then
echo "error"
exit 1
fi
#I want to echo that we begin impor"
echo "Import begin"
cat /dev/stdin | mysql -u root db
#I want to echo that import finished
echo "Import finish"
这里的挑战是不要写入物理文件。如果是这种情况,这会更容易,但是我想尽力而为。有可能吗?
答案 0 :(得分:1)
您要的内容的文字实现(不是一个好主意,但完全按照您的要求进行)可能如下所示:
这是一个坏主意,原因有几个:
base64
或uunencode
或其他工具一样)。这使其比以前大 ,并且还增加了性能开销...但是,按要求提供了错误思想代码:
#!/usr/bin/env bash
set -o pipefail # if any part of a command fails, count the whole thing a failure
if exportOutputB64=$(someExportCommand | base64); then
echo "Export database done" >&2
else
echo "Export database reports failure" >&2
exit 1
fi
if exportOutputDecompressedB64=$(base64 --decode <<<"$exportOutputB64" | gunzip -c | base64); then
echo "Decompress of export done" >&2
else
echo "Decompress of export failed" >&2
exit 1
fi
unset exportOutputB64
if grep -q 'password error' < <(base64 --decode <<<"$exportOutputDecompressedB64"); then
echo "Export contains password error; considering it a failure" >&2
exit 1
fi
echo "Import begin"
mysql -u root db < <(base64 --decode <<<"$exportOutputDecompressedB64")
如果我自己写这篇文章,我将建立一个就地处理整个事情的管道,并使用pipefail
确保在早期阶段检测到错误:
set -o pipefail
someExportCommand | gunzip -c | mysql -u root db
关于管道的重要一点是它的所有部分都同时运行。因此,someExportCommand
启动时mysql -u root db
仍在运行。因此,不需要大的缓冲区任何地方(在内存中,在磁盘上的或上)来存储数据库内容。
答案 1 :(得分:1)
不使用临时文件的要求似乎有误。但您可以通过读取shell变量或数组来避免这种情况。
任何错误消息都可能在stderr上,而不是stdin上。但是,您应该检查程序的退出状态,而不要查找程序是否显示错误消息。
#!/bin/bash
result=$(someExportCommand) || exit
这时,如果失败,脚本将退出;否则,result
包含其输出。
现在,类似于错误消息,状态消息也应打印为标准错误,而不是标准输出。常见的约定还包括在消息中包含脚本的名称。
echo "$0: Import begin" >&2
现在,将变量传递到mysql
。
mysql -u root db <<<"$result"
请注意,<<<"here string"
语法是Bash功能;您不能将其与/bin/sh
一起使用。如果您需要脚本可移植到sh
,则标准解决方案仍然是使用管道;
printf '%s\n' "$result" | mysql -u root db
最后,再次将状态消息打印到stderr。
echo "$0: Import finished" >&2
对于长字符串使用shell变量并不是特别有效或优雅;绝对建议将输出捕获到临时文件中。