gsutil cp命令输出始终流向stderr而非stdout,如何修正?
哦,这个问题我之前也碰到过!其实这不是bug,是gsutil故意设计的行为——它把所有操作相关的状态信息(不管是成功提示还是进度条)都输出到stderr,而stdout只留给实际的文件内容(比如你用gsutil cp gs://bucket/file -把文件内容输出到终端的时候)。这样做是为了避免操作日志干扰到你可能需要的文件数据输出。
下面给你几个不同场景的解决办法,按需选择:
1. 只关心错误?用安静模式抑制成功日志
如果你不需要记录或看到成功的复制提示,只想捕获错误信息,直接给gsutil cp加-q参数就行:
gsutil cp -q existed_file.txt . > out.log 2> error.log
成功复制时,out.log会是空的(毕竟没有文件内容输出到stdout),error.log也不会有任何内容;只有复制出错时,错误信息才会写入error.log。
2. 要区分成功日志和错误日志?用过滤命令分流
如果你想把成功的操作提示(比如Copying gs://xxx to ./xxx...)写到out.log,错误信息写到error.log,可以用grep配合进程替换来过滤stderr内容:
gsutil cp existed_file.txt . 2>&1 | tee >(grep -E "(Error|Failed|Exception)" > error.log) | grep -v -E "(Error|Failed|Exception)" > out.log
简单解释下逻辑:
2>&1把stderr的内容合并到stdouttee用来同时把内容输出到终端和后续的过滤命令- 第一个
grep抓取包含错误关键词的行,写入error.log - 第二个
grep反向过滤掉错误行,把剩下的成功日志写入out.log
如果不想在终端看到输出,去掉tee即可:
gsutil cp existed_file.txt . 2>&1 | grep -E "(Error|Failed|Exception)" > error.log | grep -v -E "(Error|Failed|Exception)" > out.log
3. 永久修改gsutil的输出行为?改配置文件
如果你希望所有gsutil命令都把操作日志输出到stdout,可以修改你的~/.boto配置文件(没有的话就新建一个),在[GSUtil]区块里添加:
[GSUtil] log_stderr = False
不过要注意:以后如果用gsutil输出文件内容到stdout(比如gsutil cat gs://bucket/file),日志会和文件内容混在一起,所以这个方法只适合你不需要输出文件内容到stdout的场景。
内容的提问来源于stack exchange,提问作者voxter
相关产品推荐
相关产品推荐

