我使用Python的Fabric通过ssh在远程主机上执行一些任务
当显示子任务的进度条时,其中一个任务在其输出中使用回车符。类似的东西:
int main(int argc, char* argv[]) {
int i;
for (i = 0; i <= 5; ++i) {
printf("rProgress: %d%%", (int)(100 * ((float)i / 5)));
fflush(stdout);
sleep(1);
}
printf("n");
return 0;
}
当这与python的Fabric:一起运行时
def some_task():
with settings(user = 'root'):
run('./task_with_progress_bar.out')
tasks.execute(some_task, hosts = ['server_name'])
Fabric将忽略r
,而不是将进度条放在一行中,我得到的是:
[server_name] Executing task 'some_task'
[server_name] run: ./task_with_progress_bar.out
[server_name] out:
[server_name] out: Progress: 0%
[server_name] out: Progress: 20%
[server_name] out: Progress: 40%
[server_name] out: Progress: 60%
[server_name] out: Progress: 80%
[server_name] out: Progress: 100%
[server_name] out:
似乎r
被当作n
。。。
在上面的例子中,这还不错,但我正在运行的实际任务中充满了进度条,这些进度条以较小的步骤进行,这会用不必要的输出污染整个控制台。
有没有一种方法可以自定义输出,使Fabric不会忽略r
,但仍然保持相同的通用格式:[<server_name>] <action_being_taken>
?我喜欢这种格式,它整洁。
问题是结构正在n
中转换r
。
解决这个问题的方法是创建一个类似文件的类,并将其作为stdout
参数传递给run
,这样我们就可以处理被调用程序产生的输出,并将n
翻译回r
。编写此类的挑战是确定哪些n
必须翻译为r
。以下是寻找"Progress:"
来识别此类情况的尝试:
class FixProgress:
def __init__(self):
self.saw_progress = False
def write(self, s):
if 'Progress:' in s:
self.saw_progress = True
if s == 'n' and self.saw_progress:
sys.stdout.write('r')
self.saw_progress = False
else:
sys.stdout.write(s)
def flush(self):
sys.stdout.flush()
def some_task():
with settings(user = 'root'):
run('./task_with_progress_bar.out', stdout = FixProgress())
这对问题中的c程序来说是正确的。
如果可以更改输出进度条的c文件的源代码,则可以使用isatty()测试stdin是否为tty。如果为false,则可以抑制进度条输出,使其仅以特定值更新,即间隔25。
http://linux.die.net/man/3/isatty