Executing Commands From Windows Service

T

T

I have a script, which runs as a Windows service under the LocalSystem
account, that I wish to have execute some commands. Specifically, the
program will call plink.exe to create a reverse SSH tunnel. Right now
I'm using subprocess.Popen to do so. When I run it interactively via
an admin account, all is well. However, when I'm running it via
service, no luck. I'm assuming this is to do with the fact that it's
trying to run under the LocalSystem account, which is failing. What
would be the best way around this? Thanks!
 
S

Sean DiZazzo

I have a script, which runs as a Windows service under the LocalSystem
account, that I wish to have execute some commands.  Specifically, the
program will call plink.exe to create a reverse SSH tunnel.  Right now
I'm using subprocess.Popen to do so.  When I run it interactively via
an admin account, all is well.  However, when I'm running it via
service, no luck.  I'm assuming this is to do with the fact that it's
trying to run under the LocalSystem account, which is failing.  What
would be the best way around this?  Thanks!

Try running/debugging your service from the commandline as
"<servicename> debug" That should lead you to the error.

Otherwise, we need to see a traceback and some code to be better able
to help.

~Sean
 
T

T

Try running/debugging your service from the commandline as
"<servicename> debug"  That should lead you to the error.

Otherwise, we need to see a traceback and some code to be better able
to help.

~Sean

It's working fine when I run it via "<servicename> debug" - that's how
I was testing before. It's when I start the service that it fails -
and you can see that, when you run it with debug, plink.exe runs under
my username. When I run it as a service, it runs under System...
 
S

Sean DiZazzo

It's working fine when I run it via "<servicename> debug" - that's how
I was testing before.  It's when I start the service that it fails -
and you can see that, when you run it with debug, plink.exe runs under
my username.  When I run it as a service, it runs under System...

You can have the service run as any user under the service
properties. Perhaps set the service to run under your username?

There may be some environment variables set in your session that
aren't in the one its running as. So maybe check there as well.

Off to drink beer. Good luck.
 
A

Alf P. Steinbach

* T:
It's working fine when I run it via "<servicename> debug" - that's how
I was testing before. It's when I start the service that it fails -
and you can see that, when you run it with debug, plink.exe runs under
my username. When I run it as a service, it runs under System...

This sounds like a Windows programming problem, not anything related to Python
per se.

Windows services are generally limited in what they can do, such as interaction
with the user, and I guess that spills over to network access.

Also, services need to interact with the service control manager, the "scum" as
it's known. Well, all right, that's just what my coworkers and I called it once.
But essentially, it's an even-driven execution model, which means that it might
not work to use just any program, such as [python.exe], directly as a service.

The Windows Resource Kit used to have a facility for running ordinary programs
as services. I'm not sure what it did at the technical level, but it worked. Or
it appeared to work.

You might also find it useful to look up the documentation on services that
interact with the user. In the old times that was mostly a matter of configuring
which account the service ran under. But I think it all got more complicated
with Microsoft's introduction of Terminal services (generally, most of the
complication in modern Windows is due to the shift in focus about 1995, ditching
the personal computer user market in favor of the enterprise and MIS market).

Cross-posted to [comp.os.ms-windows.programmer.win32], follow-ups set to that
group -- that means, unless overridden you won't see follow-ups in [c.l.p].

I think that group may give more informative and helpful responses.


Cheers & hth.,

- Alf
 
T

T

Thanks for the suggestions - I think my next step is to try running
it under an admin user account, as you guys both mentioned. Alf -
you're absolutely right, Microsoft has srvany.exe, which allows you to
run any EXE as a Windows service. I've done this in the past, but
it's more of a "hack"..so this go around (since I will be distributing
this program), I wanted to go the more professional route..which,
unfortunately, involves learning the "scum". :) I posted this to
comp.os.ms-windows.programmer.win32, so we'll see if what the Win32
programmers have to say as well. Thanks again!
 
S

Sean DiZazzo

Thanks for the suggestions -  I think my next step is to try running
it under an admin user account, as you guys both mentioned.  Alf -
you're absolutely right, Microsoft has srvany.exe, which allows you to
run any EXE as a Windows service.  I've done this in the past, but
it's more of a "hack"..so this go around (since I will be distributing
this program), I wanted to go the more professional route..which,
unfortunately, involves learning the "scum". :)  I  posted this to
comp.os.ms-windows.programmer.win32, so we'll see if what the Win32
programmers have to say as well.  Thanks again!

I use windows services and they are very reliable. I would say though
that relying on plink.exe is much less reliable than either python or
the service that it is running under.

Why not take a look at paramiko as the ssh client library? I think it
runs under windows. Also perhaps Twisted has something. Either way
would be light years ahead of using subprocess with plink.

Just my thoughts.

~Sean
 
T

T

I use windows services and they are very reliable.  I would say though
that relying on plink.exe is much less reliable than either python or
the service that it is running under.

Why not take a look at paramiko as the ssh client library?  I think it
runs under windows.  Also perhaps Twisted has something.  Either way
would be light years ahead of using subprocess with plink.

Just my thoughts.

~Sean

I totally agree that it would be much more reliable to use a Python
library for SSH - however, the program will need to execute other
external binaries as well. So my goal at this point is to track down
_why_ it's failing when running as a service. The actual command is
as follows:

C:\plink.exe -R 9999:127.0.0.1:2020 -batch -i C:\keyfile.ppk
[email protected]

I tried having subprocess.Popen run plink.exe by itself and piping
output to file, and this worked - so I know it's at least executing
plink.exe. Sorry, I realize this isn't truly just a Python-related
question, but any help would be greatly appreciated! So far no help
at comp.os.ms-windows.programmer.win32..
 
D

David Bolen

T said:
I have a script, which runs as a Windows service under the LocalSystem
account, that I wish to have execute some commands. Specifically, the
program will call plink.exe to create a reverse SSH tunnel. Right now
I'm using subprocess.Popen to do so. When I run it interactively via
an admin account, all is well. However, when I'm running it via
service, no luck. I'm assuming this is to do with the fact that it's
trying to run under the LocalSystem account, which is failing. What
would be the best way around this? Thanks!

The LocalSystem account is not, if I recall correctly, permitted to
access the network.

You'll have to install the service to run under some other account that
has appropriate access to the network.

-- David
 
T

T

The LocalSystem account is not, if I recall correctly, permitted to
access the network.

You'll have to install the service to run under some other account that
has appropriate access to the network.

-- David

The more testing I do, I think you may be right..I was able to get it
to work under a local admin account, and it worked under debug mode
(which would also have been running as this user). I'm a bit
surprised though - I was under the assumption that LocalSystem had
rights to access the network?
 
S

Sean DiZazzo

The more testing I do, I think you may be right..I was able to get it
to work under a local admin account, and it worked under debug mode
(which would also have been running as this user).  I'm a bit
surprised though - I was under the assumption that LocalSystem had
rights to access the network?

You really need a way to see the error you are getting. If you can't
get it to show you the error in the shell, set up some logging to a
file, and find the error that way. I think the user can access the
network just fine, but that maybe plink.exe is not in his path or some
such thing.

Find the error!
 
D

David Bolen

T said:
The more testing I do, I think you may be right..I was able to get it
to work under a local admin account, and it worked under debug mode
(which would also have been running as this user). I'm a bit
surprised though - I was under the assumption that LocalSystem had
rights to access the network?

Not from my past experience - the system account (LocalSystem for
services) can be surprising, in that it's pretty much unlimited access
to all local resources, but severely limited in a handful of cases,
one of which is any attempt to access the network. I can't recall for
sure if it's an absolute block, or if in some cases you can configure
around it (e.g., it might use a null session for remote shares which
can be enabled through the registry on the target machine). I've
basically stuck "LocalSystem = no network" in my head from past
experience.

So you can either install your service to run under your existing
account, or create an account specifically for running your service,
granting that account just the rights it needs.

-- David
 
D

David Bolen

David Bolen said:
Not from my past experience - the system account (LocalSystem for
services) can be surprising, in that it's pretty much unlimited access
to all local resources, but severely limited in a handful of cases,
one of which is any attempt to access the network. I can't recall for
sure if it's an absolute block, or if in some cases you can configure
around it (e.g., it might use a null session for remote shares which
can be enabled through the registry on the target machine). I've
basically stuck "LocalSystem = no network" in my head from past
experience.

Given it's been a few years, I decided to try some tests, and the
above is too simplistic.

The LocalSystem account runs without any local Windows credentials
(e.g., not like a logged in user), which has several consequences.
One is that you can't access any network resources that require such
credentials (like shares). However, there's no sort of firewall
filtering or anything, so plain old TCP/IP connections are fine.
Unless, of course, the client being used also has other needs for
local Windows credentials, independent or as a pre-requisite to the
network operations.

So backing up a bit, the TCP/IP connection that plink is making is not
inherently disabled by running under LocalSystem, but it's certainly
possible that plink is trying to identify the user under which it is
operating to perhaps identify ssh keys or other local resources it
needs to operate. You might be able to cover this with command line
options (e.g., plink supports "-i" to specify a key file to use), but
you'll also need to ensure that the file you are referencing is
readable by the LocalSystem account.

One of the other responders had a very good point about locating plink
in the first place too. Services run beneath an environment that is
inherited from the service control manager process, and won't include
various settings that are applied to your user when logged in,
especially things like local path changes, and working directories.
Should you change the system path (via the environment settings),
you'll need to reboot for the service control manager to notice - I
don't think you can restart it without a reboot.

So it's generally safer to be very clear, and absolute when possible,
in a service for paths to external resources.

The prior advice of running the service as an identified user (e.g.,
with local credentials) is still good as it does remove most of these
issues since if you can run the script manually under that user you
know it'll work under service. But it's not a hard requirement.

If your script is dying such that a top level exception is being
raised you should be able to find it in the application event log. So
that might give further information on what about the different
environment is problematic.

You can also use the win32traceutil module to help with grabbing debug
output on the fly. Import the module in your service, which will
implicitly redirect stdout/stderr to a trace buffer. Run the same
win32traceutil module from the command line in another window. Then
start the service. Any stdout/stderr will be reflected in the other
window. Can't catch everything (suppressed exceptions, or I/O that
doesn't flow through the script's stdout/stderr), but again might help
point in the right direction.

-- David
 
T

T

Given it's been a few years, I decided to try some tests, and the
above is too simplistic.

The LocalSystem account runs without any local Windows credentials
(e.g., not like a logged in user), which has several consequences.
One is that you can't access any network resources that require such
credentials (like shares).  However, there's no sort of firewall
filtering or anything, so plain old TCP/IP connections are fine.
Unless, of course, the client being used also has other needs for
local Windows credentials, independent or as a pre-requisite to the
network operations.

So backing up a bit, the TCP/IP connection that plink is making is not
inherently disabled by running under LocalSystem, but it's certainly
possible that plink is trying to identify the user under which it is
operating to perhaps identify ssh keys or other local resources it
needs to operate.  You might be able to cover this with command line
options (e.g., plink supports "-i" to specify a key file to use), but
you'll also need to ensure that the file you are referencing is
readable by the LocalSystem account.

One of the other responders had a very good point about locating plink
in the first place too.  Services run beneath an environment that is
inherited from the service control manager process, and won't include
various settings that are applied to your user when logged in,
especially things like local path changes, and working directories.
Should you change the system path (via the environment settings),
you'll need to reboot for the service control manager to notice - I
don't think you can restart it without a reboot.

So it's generally safer to be very clear, and absolute when possible,
in a service for paths to external resources.

The prior advice of running the service as an identified user (e.g.,
with local credentials) is still good as it does remove most of these
issues since if you can run the script manually under that user you
know it'll work under service.  But it's not a hard requirement.

If your script is dying such that a top level exception is being
raised you should be able to find it in the application event log.  So
that might give further information on what about the different
environment is problematic.

You can also use the win32traceutil module to help with grabbing debug
output on the fly.  Import the module in your service, which will
implicitly redirect stdout/stderr to a trace buffer.  Run the same
win32traceutil module from the command line in another window.  Then
start the service.  Any stdout/stderr will be reflected in the other
window.  Can't catch everything (suppressed exceptions, or I/O that
doesn't flow through the script's stdout/stderr), but again might help
point in the right direction.

-- David

Great suggestions once again - I did verify that it was at least
running the plink.exe binary when under LocalSystem by having the
service run "plink.exe > C:\plinkoutput.txt" - this worked fine. And,
as I mentioned, it's now working just fine when running under a
regular admin account. So, I think that's going to be my solution to
avoid any further issues. My best guess at this point (as you
mentioned), is that plink.exe is doing _something_ network-related
that LocalSystem doesn't have the privileges to do - what exactly it
is, I have no idea. I may play around with it some more later, but
running the service under an admin account should be a perfectly
acceptable solution.

Also, I will be writing other Python apps that the service will be
executing - so it goes without saying that I'll be including a log to
file option :) Thanks again for all your guys' help!
 
T

Tim Golden

Great suggestions once again - I did verify that it was at least
running the plink.exe binary when under LocalSystem by having the
service run "plink.exe> C:\plinkoutput.txt" - this worked fine. And,
as I mentioned, it's now working just fine when running under a
regular admin account. So, I think that's going to be my solution to
avoid any further issues. My best guess at this point (as you
mentioned), is that plink.exe is doing _something_ network-related
that LocalSystem doesn't have the privileges to do - what exactly it
is, I have no idea. I may play around with it some more later, but
running the service under an admin account should be a perfectly
acceptable solution.

Also, I will be writing other Python apps that the service will be
executing - so it goes without saying that I'll be including a log to
file option :) Thanks again for all your guys' help!

I'm not sure if this has been said already, but a reasonably common
approach to services is to create a user specifically for the
service and grant it exactly the privs / perms it needs (once you
work out what they are). You then assign it a generated password,
eg a GUID which you don't even try to remember: simply cut-and-paste
it in. Then create the service to run under that user.

That way you don't have the service running under
some local Administrator account with the associated risk
of its being subverted and gaining more control than you
want. Nor do you have it running as a real user whose
password might change for any reason, leaving you with
a service which won't start up.

I don't remember at this moment whether such a user's profile
is automatically loaded in the process when the service starts
or whether you have to do the LoadUserProfile thing.

TJG
 
M

Martin P. Hellwig

I have a script, which runs as a Windows service under the LocalSystem
account, that I wish to have execute some commands. Specifically, the
program will call plink.exe to create a reverse SSH tunnel. Right now
I'm using subprocess.Popen to do so. When I run it interactively via
an admin account, all is well. However, when I'm running it via
service, no luck. I'm assuming this is to do with the fact that it's
trying to run under the LocalSystem account, which is failing. What
would be the best way around this? Thanks!

All being said about LS account not having the appropriate rights to
access the necessary devices/files.

Could it be so simple that the network is plain simply not available at
all? For wireless connections I believe the connection/authentication by
default is made in user space. I would save the output of an ipconfig
run as the LS account to a file and see what is happening.
Perhaps followed by a ping.
 
T

T

I'm not sure if this has been said already, but a reasonably common
approach to services is to create a user specifically for the
service and grant it exactly the privs / perms it needs (once you
work out what they are). You then assign it a generated password,
eg a GUID which you don't even try to remember: simply cut-and-paste
it in. Then create the service to run under that user.

That way you don't have the service running under
some local Administrator account with the associated risk
of its being subverted and gaining more control than you
want. Nor do you have it running as a real user whose
password might change for any reason, leaving you with
a service which won't start up.

I don't remember at this moment whether such a user's profile
is automatically loaded in the process when the service starts
or whether you have to do the LoadUserProfile thing.

TJG

Tim - thanks, that's the route I'm going to go. I've created separate
accounts for services before, and there's no question that's what I
have to do in this case. I'm still having some issues running some
commands (such as one that takes a screenshot), even as an admin user,
but I think this is more due to the fact that it's trying to interact
with the Desktop..so there may be no good solution.

Btw great site..can't tell you how many times I've gone back to it.
Keep up the great work!
 
T

T

All being said about LS account not having the appropriate rights to
access the necessary devices/files.

Could it be so simple that the network is plain simply not available at
all? For wireless connections I believe the connection/authentication by
default is made in user space. I would save the output of an ipconfig
run as the LS account to a file and see what is happening.
Perhaps followed by a ping.

Martin - another part of the program sends an email back to a
specified user, and that works, so LocalSystem must at least have some
network access. From the testing I've done so far, seems like there's
just some grey area (which I haven't completely figured out yet) of
network-related tasks that LS just can't do. I'd love to know what
this is, but so far the solution I have is just to create another user
and have the service use that..
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,983
Messages
2,570,187
Members
46,747
Latest member
jojoBizaroo

Latest Threads

Top