Using sudo to write to a file as root from a script

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Using sudo to write to a file as root from a script

Adam Mercer
Hi

I'm trying to write a script that writes some content to a file root
through sudo, but it's not working at all. I am using:

  channel = 'stable'
  config_file = '/opt/ldg/etc/channel.conf'
  command = ['echo', '-n', channel, '|', 'sudo', 'tee', config_file]
  p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  out, _ = p.communicate()

But it seems as if this isn't doing anything.

I just want to write the contents of the variable channel to the file
/opt/ldg/etc/channel.conf. But whatever I try just doesn't work. Can
anyone offer any pointers?

Cheers

Adam


Reply | Threaded
Open this post in threaded view
|

Using sudo to write to a file as root from a script

David-712
On 9 August 2013 14:11, Adam Mercer <ramercer at gmail.com> wrote:
>
> I'm trying to write a script that writes some content to a file root
> through sudo, but it's not working at all. I am using:

[...]

At a quick glance, I have a couple of suggestions.

>   command = ['echo', '-n', channel, '|', 'sudo', 'tee', config_file]

sudo doesn't work like this. It doesn't read from standard input. You
need to supply the command as an argument to sudo. Get the sudo syntax
correct by learning to use it in a shell (eg terminal running bash )
before trying to use it from python code.

Also, I think that passing the pipe character '|' as an argument to
Popen is not the correct way to use pipes.

So, if you figure out how to use sudo without '|' you will solve both
these issues.


Reply | Threaded
Open this post in threaded view
|

Using sudo to write to a file as root from a script

IshIsh
Am 09.08.2013 05:47, schrieb David:

> On 9 August 2013 14:11, Adam Mercer <ramercer at gmail.com> wrote:
>>
>> I'm trying to write a script that writes some content to a file root
>> through sudo, but it's not working at all. I am using:
>
> [...]
>
> At a quick glance, I have a couple of suggestions.
>
>>   command = ['echo', '-n', channel, '|', 'sudo', 'tee', config_file]
>
> sudo doesn't work like this. It doesn't read from standard input. You
> need to supply the command as an argument to sudo. Get the sudo
> syntax
> correct by learning to use it in a shell (eg terminal running bash )
> before trying to use it from python code.
>
> Also, I think that passing the pipe character '|' as an argument to
> Popen is not the correct way to use pipes.
>
> So, if you figure out how to use sudo without '|' you will solve both
> these issues.

Or try to change the permissions

os.system("chmod 666 config_file)

do what you want with the file and set the permissions back to their
original state.


Reply | Threaded
Open this post in threaded view
|

Using sudo to write to a file as root from a script

Adam Mercer
In reply to this post by David-712
On Thu, Aug 8, 2013 at 11:47 PM, David <bouncingcats at gmail.com> wrote:

> At a quick glance, I have a couple of suggestions.
>
>>   command = ['echo', '-n', channel, '|', 'sudo', 'tee', config_file]
>
> sudo doesn't work like this. It doesn't read from standard input. You
> need to supply the command as an argument to sudo. Get the sudo syntax
> correct by learning to use it in a shell (eg terminal running bash )
> before trying to use it from python code.

The above does works in the terminal:

[ram at cizin ~]$ ls -l /opt/ldg/etc/
total 20
-rw-rw-r-- 1 ram admin 5246 Jun 14 15:15 globus-user-env.csh
-rw-rw-r-- 1 ram admin 3388 Jun 14 15:15 globus-user-env.sh
-rw-rw-r-- 1 ram admin   91 Jun 24 11:33 ldg.conf
-rw-r--r-- 1 ram admin    5 Jun 14 15:24 os.conf
$ echo -n stable | sudo tee /opt/ldg/etc/channel.conf > /dev/null
Password:
$ ls -l /opt/ldg/etc/
total 24
-rw-r--r-- 1 root admin    6 Aug  9 07:59 channel.conf
-rw-rw-r-- 1 ram  admin 5246 Jun 14 15:15 globus-user-env.csh
-rw-rw-r-- 1 ram  admin 3388 Jun 14 15:15 globus-user-env.sh
-rw-rw-r-- 1 ram  admin   91 Jun 24 11:33 ldg.conf
-rw-r--r-- 1 ram  admin    5 Jun 14 15:24 os.conf
$

Thats why I'm trying to use it.

> Also, I think that passing the pipe character '|' as an argument to
> Popen is not the correct way to use pipes.

I believe subprocess uses pipes as follows
import subprocess
with open("/opt/ldg/etc/channel.conf","w") as out:
  subprocess.Popen(command, stdout=out)

Then the file wouldn't be opened as root? And if the file already
exists then I wouldn't be able to open it due to incorrect
permissions.

> So, if you figure out how to use sudo without '|' you will solve both
> these issues.

I'm open to suggestions as everything I can find involved pipes or
redirections and neither seems to work with subprocess. I can use
subprocess.call() as in:

import subprocess
import sys

channel='stable'
config_file='/opt/ldg/etc/channel.conf'
command="echo -n %s | sudo tee %s > /dev/null" % (channel, config_file)

try:
  retcode = subprocess.call(command, shell=True)
  if retcode < 0:
    sys.exit('Error: Failed to set channel.conf')
except OSError as e:
  sys.exit('Error: Execution failed "%s"' % e)

But I was under the impression that Popen was the preferred approach
to running external processes?

Cheers

Adam


Reply | Threaded
Open this post in threaded view
|

Using sudo to write to a file as root from a script

Chris Angelico
On Fri, Aug 9, 2013 at 2:21 PM, Adam Mercer <ramercer at gmail.com> wrote:
> command="echo -n %s | sudo tee %s > /dev/null" % (channel, config_file)
>


You shouldn't need to use 'echo' here. Just provide tee with the text
on its standard input, and don't bother with the pipe at all.

ChrisA


Reply | Threaded
Open this post in threaded view
|

Using sudo to write to a file as root from a script

Antoon Pardon
Op 09-08-13 15:29, Chris Angelico schreef:
> On Fri, Aug 9, 2013 at 2:21 PM, Adam Mercer <ramercer at gmail.com> wrote:
>> command="echo -n %s | sudo tee %s > /dev/null" % (channel, config_file)
>>
>
> You shouldn't need to use 'echo' here. Just provide tee with the text
> on its standard input, and don't bother with the pipe at all.

That is probably beside the point. I suspect Adam is just giving a
minimal example to show the kind of thing he is trying to do.

Nit picking the specific example instead of advising on the problem
is likely to be less than helpful.

--
Antoon Pardon


Reply | Threaded
Open this post in threaded view
|

Using sudo to write to a file as root from a script

Adam Mercer
In reply to this post by Chris Angelico
On Fri, Aug 9, 2013 at 8:29 AM, Chris Angelico <rosuav at gmail.com> wrote:

> You shouldn't need to use 'echo' here. Just provide tee with the text
> on its standard input, and don't bother with the pipe at all.

Thanks, that's much better!

Cheers

Adam


Reply | Threaded
Open this post in threaded view
|

Using sudo to write to a file as root from a script

Adam Mercer
In reply to this post by Antoon Pardon
On Fri, Aug 9, 2013 at 8:42 AM, Antoon Pardon
<antoon.pardon at rece.vub.ac.be> wrote:

> That is probably beside the point. I suspect Adam is just giving a
> minimal example to show the kind of thing he is trying to do.
>
> Nit picking the specific example instead of advising on the problem
> is likely to be less than helpful.

It is a simplified example, but in this case the nitpicking was very
helpful. Caused me to think about the problem differently, and
therefore come up with a neater solution.

Cheers

Adam


Reply | Threaded
Open this post in threaded view
|

Using sudo to write to a file as root from a script

Antoon Pardon
In reply to this post by Adam Mercer
Op 09-08-13 06:11, Adam Mercer schreef:

> Hi
>
> I'm trying to write a script that writes some content to a file root
> through sudo, but it's not working at all. I am using:
>
>   channel = 'stable'
>   config_file = '/opt/ldg/etc/channel.conf'
>   command = ['echo', '-n', channel, '|', 'sudo', 'tee', config_file]
>   p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>   out, _ = p.communicate()
>
> But it seems as if this isn't doing anything.
>
> I just want to write the contents of the variable channel to the file
> /opt/ldg/etc/channel.conf. But whatever I try just doesn't work. Can
> anyone offer any pointers?
>
> Cheers
>
> Adam

subprocess.Popen by default doesn't use a shell. That could mean that
the equivallent shell command you are trying to execute is:

  echo -n stable '|' sudo tee /opt/ldg/etc/channel.conf

instead of

  echo -n stable | sudo tee /opt/ldg/etc/channel.conf

which you probably want.


You should also take care with the echo command. Echo is
usually a shell builtin that can behave differently than
the echo command. You should make sure you are using the
one you actually want to use.

--
Antoon Pardon


Reply | Threaded
Open this post in threaded view
|

Using sudo to write to a file as root from a script

Chris Angelico
In reply to this post by Adam Mercer
On Fri, Aug 9, 2013 at 2:50 PM, Adam Mercer <ramercer at gmail.com> wrote:

> On Fri, Aug 9, 2013 at 8:42 AM, Antoon Pardon
> <antoon.pardon at rece.vub.ac.be> wrote:
>
>> That is probably beside the point. I suspect Adam is just giving a
>> minimal example to show the kind of thing he is trying to do.
>>
>> Nit picking the specific example instead of advising on the problem
>> is likely to be less than helpful.
>
> It is a simplified example, but in this case the nitpicking was very
> helpful. Caused me to think about the problem differently, and
> therefore come up with a neater solution.

It wasn't nitpicking so much as suggesting a more Pythonic way to do
things. It's entirely plausible that the response would have been
"Actually, the real command is more complicated than 'echo' so I
really do need a pipe", but it's *very* common in shell scripts to
call on an external process to do something that in other languages is
a builtin. For instance, how do you get the name of the parent of your
current directory in bash? Something along the lines of:

parent=$(dirname $(pwd$)$)

which executes two external commands. In Python, it would be:

os.path.dirname(os.getcwd())

which is two internal function calls. It's just one of the things to
consider when porting code from one language to another - I wouldn't
often use a list comprehension in bash, and I wouldn't often want a
pipe between two external processes in Python.

ChrisA


Reply | Threaded
Open this post in threaded view
|

Using sudo to write to a file as root from a script

David-712
In reply to this post by Adam Mercer
On 9 August 2013 23:21, Adam Mercer <ramercer at gmail.com> wrote:

> On Thu, Aug 8, 2013 at 11:47 PM, David <bouncingcats at gmail.com> wrote:
>
>> At a quick glance, I have a couple of suggestions.
>>
>>>   command = ['echo', '-n', channel, '|', 'sudo', 'tee', config_file]
>>
>> sudo doesn't work like this. It doesn't read from standard input. You
>> need to supply the command as an argument to sudo. Get the sudo syntax
>> correct by learning to use it in a shell (eg terminal running bash )
>> before trying to use it from python code.
>
> The above does works in the terminal:

Ah, sorry, I didn't pay close attention to what you are doing (with tee).

>> So, if you figure out how to use sudo without '|' you will solve both
>> these issues.

At least I wasn't 100% wrong :)
Anyway I'm glad some smarter people helped you.