Я пытаюсь скопировать некоторые файлы по следующей схеме:

/var/lib/cassandra/data/*/*/snapshots/<snapid>/

Если я выполняю команду tar вручную, она работает без проблем, но когда я выполняю ее с помощью python, она не работает.

Я выполняю это следующим образом:

    output = subprocess.check_output(["tar","cf", outputfile, snappath])

Но пока я получаю следующую ошибку, я могу сменить файл вручную

tar: /var/lib/cassandra/data/*/*/snapshots/20151215104608: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors
Traceback (most recent call last):
  File "./cassandrabackup2s3.py", line 68, in <module>
    create_snapshot_file(snapid)
  File "./cassandrabackup2s3.py", line 46, in create_snapshot_file
    output = subprocess.check_output(["tar","cf", outputfile, snappath])
  File "/usr/lib64/python2.7/subprocess.py", line 575, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['tar', 'cf', '/tmp/20151215104608.tgz', '/var/lib/cassandra/data/*/*/snapshots/20151215104608/']' returned non-zero exit status 2

Я видел несколько сообщений об удалении "-" из -cvzf или использовании shell = True, но ничего не работает. Вот вывод с использованием Shell=True

 output = subprocess.check_output(["tar","cf", outputfile, snappath], shell=True)

Кажется, что синтаксис tar неверен:

tar: You must specify one of the `-Acdtrux' or `--test-label'  options
Try `tar --help' or `tar --usage' for more information.
Traceback (most recent call last):
  File "./cassandrabackup2s3.py", line 68, in <module>
    create_snapshot_file(snapid)
  File "./cassandrabackup2s3.py", line 46, in create_snapshot_file
    output = subprocess.check_output(["tar","cf", outputfile, snappath], shell=True)
  File "/usr/lib64/python2.7/subprocess.py", line 575, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['tar', 'cf', '/tmp/20151215103816.tgz', '/var/lib/cassandra/data/*/*/snapshots/20151215103816/']' returned non-zero exit status 2

Я пытался использовать библиотеку tar, но кажется, что регулярное выражение * не работает

1
RuBiCK 15 Дек 2015 в 13:55

3 ответа

Лучший ответ

Когда вы запускаете эту команду в приглашении оболочки, оболочка расширяет подстановочные знаки. Если вы хотите, чтобы Python использовал расширение по шаблону, вы должны запросить его отдельно.

Из вашего вопроса не ясно, какая часть не работает, но я думаю, вы хотите

cmd = ['tar', 'cf', outputfile]
cmd.extend(glob.glob(snappath))
output = subprocess.check_output(cmd)

Добавление shell=True решило бы вашу проблему, если бы вы не использовали список аргументов для subprocess; тогда оболочка проанализировала бы строку и выполнила бы подстановочный знак. Но когда вы предоставляете список, shell=True ничего не делает, потому что вы (как предполагается) уже выполнили анализ командной строки, который будет выполнять оболочка. Но, как правило, если ваши потребности просты, вы все равно должны избегать shell=True, так как сама оболочка создает ряд сложностей, о которых вам необходимо знать.

3
tripleee 15 Дек 2015 в 11:27

Вместо этого я предлагаю использовать библиотеку tarfile: https://docs.python.org/2/library /tarfile.html

Отредактировано, чтобы дать вам пример:

import glob
import tarfile
snaps = glob.glob("/var/lib/cassandra/data/*/*/snapshots/<snapid>/")
with tarfile.open("tared.tar","w") as tar:
    for snap in snaps:
         tar.add(snap)
0
Radek 15 Дек 2015 в 11:41

Когда вы запускаете tar в командной строке, тогда путь:

/var/lib/cassandra/data/*/*/snapshots/<snapid>/

Раскрывается shell , а не командой tar. check_output не будет выполнять это * расширение, поэтому вы правы, что вам нужен shell=True, чтобы существовала оболочка для расширения этих переменных.

Однако, чтобы использовать оболочку, вы должны дать функциям подпроцесса строку, а не список:

output = subprocess.check_output("echo my command is here", shell=True)

Итак, ваша команда tar перенесена в две отдельные строки для ясности:

command = "tar cf {} {}".format(outputfile, snappath)
output = subprocess.check_output(command, shell=True)

Как говорит @radek, вы также можете использовать модуль tar: https: //docs.python. орг / 2 / библиотека / tarfile.html

0
Simon Fraser 15 Дек 2015 в 11:18