Python:使用管道的子进程,在失败时退出

时间:2015-10-07 13:14:50

标签: python subprocess

我试图阻止上传到S3,以防任何先前的流水线命令失败,遗憾的是,这两种方法都没有按预期工作:

外壳管道

 Collections.sort(list);
 Collections.sort(list, new Comparator<String> (){
            public int compare(String s1, String s2){
                if(s1.toUpperCase().contains("DAY") &&     s2.toUpperCase().contains("DAY") 
                            && !s1.equalsIgnoreCase("DAY")  && !s2.equalsIgnoreCase("DAY")){

                    try{
                        Integer i1 = Integer.valueOf(s1.split("\\/")[1]);
                        Integer i2 = Integer.valueOf(s2.split("\\/")[1]);                           
                        System.out.println(" s1 " + s1 +" and s2 "+ s2 +" compare --> "+s1.compareTo(s2));

                        if(s1.compareTo(s2) > 0){
                            return 1;
                        }else if(s1.compareTo(s2) < 0){
                            if(i1 > i2){
                                return 1;
                            }else{
                                return 0;
                            }
                        }else{
                            return 0;
                        }
                    }catch(Exception e){                            
                        return s1.compareTo(s2);
                    }
                }else{
                    System.out.println("In else--");
                    return 0;
                }
            }

        });

打开PIPE

for database in sorted(databases):
    cmd = "bash -o pipefail -o errexit -c 'mysqldump -B {database} | gpg -e -r {GPGRCPT} | gof3r put -b {S3_BUCKET} -k {database}.sql.e'".format(database = database, GPGRCPT = GPGRCPT, S3_BUCKET = S3_BUCKET)
    try:
        subprocess.check_call(cmd, shell = True, executable="/bin/bash")
    except subprocess.CalledProcessError as e:
        print e

我试过这样的事情没有运气:

for database in sorted(databases):
try:
    cmd_mysqldump = "mysqldump {database}".format(database = database)
    p_mysqldump = subprocess.Popen(shlex.split(cmd_mysqldump), stdout=subprocess.PIPE)

    cmd_gpg = "gpg -a -e -r {GPGRCPT}".format(GPGRCPT = GPGRCPT)
    p_gpg = subprocess.Popen(shlex.split(cmd_gpg), stdin=p_mysqldump.stdout, stdout=subprocess.PIPE)
    p_mysqldump.stdout.close()

    cmd_gof3r = "gof3r put -b {S3_BUCKET} -k {database}.sql.e".format(S3_BUCKET = S3_BUCKET, database = database)
    p_gof3r = subprocess.Popen(shlex.split(cmd_gof3r), stdin=p_gpg.stdout, stderr=open("/dev/null"))
    p_gpg.stdout.close()
except subprocess.CalledProcessError as e:
            print e

基本上.... if p_gpg.returncode == 0: cmd_gof3r = "gof3r put -b {S3_BUCKET} -k {database}.sql.e".format(S3_BUCKET = S3_BUCKET, database = database) p_gof3r = subprocess.Popen(shlex.split(cmd_gof3r), stdin=p_gpg.stdout, stderr=open("/dev/null")) p_gpg.stdout.close() ... 即使有错误也会将数据流式传输到S3,例如当我故意更改gof3r时 - > mysqldump生成错误。

2 个答案:

答案 0 :(得分:1)

管道中的所有命令同时运行,例如:

$ nonexistent | echo it is run

即使echo命令不存在,nonexistent也始终运行。

  • pipefail会影响整个管道的退出状态 - 它不会让gof3r退出
  • errexit无效,因为此处只有一个管道。

如果您不想启动下一个管道,如果上一次迭代中的那个失败,则将break放在异常处理程序中print e之后。

p_gpg.returncode is None正在运行时

gpg。如果gof3r失败则不希望gpg运行,那么您必须首先将gpg的输出保存在其他位置,例如,在文件中:

filename = 'gpg.out'
for database in sorted(databases):
    pipeline_no_gof3r = ("bash -o pipefail -c 'mysqldump -B {database} | "
                         "gpg -e -r {GPGRCPT}'").format(**vars())
    with open(filename, 'wb', 0) as file:
        if subprocess.call(shlex.split(pipeline_no_gof3r), stdout=file):
            break # don't upload to S3, don't run the next database pipeline
    # upload the file on success
    gof3r_cmd = 'gof3r put -b {S3_BUCKET} -k {database}.sql.e'.format(**vars())
    with open(filename, 'rb', 0) as file:
        if subprocess.call(shlex.split(gof3r_cmd), stdin=file):
            break # don't run the next database pipeline

答案 1 :(得分:0)

我有完全相同的问题,我用它来管理:

cmd = "cat file | tr -d '\\n'"

subprocess.check_call( [ '/bin/bash' , '-o' , 'pipefail' , '-c' , cmd ] )

回想一下,在我的代码中搜索,我也使用了另一种方法:

subprocess.check_call( "ssh -c 'make toto 2>&1 | tee log.txt ; exit ${PIPESTATUS[0]}'", shell=True )