giomanda
giomanda

Reputation: 177

os.system command not found after string formatting

I am trying to pass a variable inside an os.system command however i get an error message "command not found" after the string formatting mark. It seems that it tries to execute the text right after the string formatting as command.

import os

BOOT_VOLUME_ATTACHMENT_ID = os.popen("terraform output | grep volume_attachment_id | cut -d ' ' -f 3").read()

os.system('oci compute boot-volume-attachment detach --force  --wait-for-state DETACHED --boot-volume-attachment-id {0} --region region1' .format(BOOT_VOLUME_ATTACHMENT_ID))

The result is the error bellow:

sh: line 1: --region: command not found

Why is python trying to execute the string right after the string formatting as a command?

I am using Python2.7

UPDATE .

It seems that the problem is in the variable BOOT_VOLUME_ATTACHMENT_ID . If i change this variable to a manual string , say "123" it works fine. However if i use os.popen then i see the mentioned error

Upvotes: 0

Views: 1061

Answers (1)

glglgl
glglgl

Reputation: 91149

Apart from os.system being by way inferior to subprocess, the likely problem is the substitution process done by .format().

Instead of your code, you should try

BOOT_VOLUME_ATTACHMENT_ID = "123"
print(repr('oci compute boot-volume-attachment detach --force  --wait-for-state DETACHED --boot-volume-attachment-id {0} --region region1'.format(BOOT_VOLUME_ATTACHMENT_ID)))

and look what it outputs.

This will tell you if there is something strange (e. g. a line break) before the --region.

After your question update, it becomes clear that your BOOT_VOLUME_ATTACHMENT_ID isn't what you claimed it to be. Instead, it contains the output of a different program, which in most cases adds a line break at the end.

If you take that content and plug it into a string the way you did, this line break gets transferred into the destination string, telling the shell to execute two commands.

The solution is to use .strip() immediately after the os.popen() call.


About subprocess:

Your program will become cleaner (e. g. less injection-prone) if you do

import subprocess
BOOT_VOLUME_ATTACHMENT_ID = "123"
subprocess.call(['oci', 'compute', 'boot-volume-attachment', 'detach', '--force', '--wait-for-state', 'DETACHED', '--boot-volume-attachment-id', BOOT_VOLUME_ATTACHMENT_ID, '--region', 'region1'])

The reason is that this avoids having the shell between your program and oci, thus eliminating one potential source of errors.

Upvotes: 2

Related Questions