Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
732f633c
Commit
732f633c
authored
Jul 18, 2016
by
Hanno Schlichting
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update zopectl, support transcript argument added in zdaemon 4.0.1.
parent
b50d6f6b
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
97 additions
and
77 deletions
+97
-77
src/Zope2/Startup/zopectl.py
src/Zope2/Startup/zopectl.py
+97
-77
No files found.
src/Zope2/Startup/zopectl.py
View file @
732f633c
...
@@ -27,6 +27,7 @@ Options:
...
@@ -27,6 +27,7 @@ Options:
-u/--user -- run the daemon manager program as this user (or numeric id)
-u/--user -- run the daemon manager program as this user (or numeric id)
-m/--umask -- provide octal umask for files created by the managed process
-m/--umask -- provide octal umask for files created by the managed process
-s/--socket-name -- socket between zopectl and zdrun
-s/--socket-name -- socket between zopectl and zdrun
-t/--transcript FILE -- log file where to redirect stdout and stderr
action [arguments] -- see below
action [arguments] -- see below
Actions are commands like "start", "stop" and "status". If -i is
Actions are commands like "start", "stop" and "status". If -i is
...
@@ -51,6 +52,9 @@ from zdaemon.zdoptions import ZDOptions
...
@@ -51,6 +52,9 @@ from zdaemon.zdoptions import ZDOptions
from
ZConfig.components.logger.handlers
import
FileHandlerFactory
from
ZConfig.components.logger.handlers
import
FileHandlerFactory
from
ZConfig.datatypes
import
existing_dirpath
from
ZConfig.datatypes
import
existing_dirpath
if
sys
.
version_info
>
(
3
,
0
):
basestring
=
str
WIN
=
False
WIN
=
False
if
sys
.
platform
[:
3
].
lower
()
==
"win"
:
if
sys
.
platform
[:
3
].
lower
()
==
"win"
:
WIN
=
True
WIN
=
True
...
@@ -58,12 +62,12 @@ if sys.platform[:3].lower() == "win":
...
@@ -58,12 +62,12 @@ if sys.platform[:3].lower() == "win":
import
win32service
import
win32service
import
win32serviceutil
import
win32serviceutil
from
nt_svcutils
import
service
from
nt_svcutils
import
service
def
do_windows
(
command
):
def
do_windows
(
command
):
def
inner
(
self
,
arg
):
def
inner
(
self
,
arg
):
name
=
self
.
get_service_name
()
name
=
self
.
get_service_name
()
display_name
=
'Zope instance at '
+
self
.
options
.
directory
display_name
=
'Zope instance at '
+
self
.
options
.
directory
# This class exists only so we can take advantage of
# This class exists only so we can take advantage of
# win32serviceutil.HandleCommandLine, it is never
# win32serviceutil.HandleCommandLine, it is never
...
@@ -79,24 +83,26 @@ if sys.platform[:3].lower() == "win":
...
@@ -79,24 +83,26 @@ if sys.platform[:3].lower() == "win":
argv
.
append
(
command
)
argv
.
append
(
command
)
# we need to supply this manually as HandleCommandLine guesses wrong
# we need to supply this manually as HandleCommandLine guesses wrong
serviceClassName
=
os
.
path
.
splitext
(
service
.
__file__
)[
0
]
+
'.Service'
serviceClassName
=
os
.
path
.
splitext
(
service
.
__file__
)[
0
]
+
'.Service'
err
=
win32serviceutil
.
HandleCommandLine
(
err
=
win32serviceutil
.
HandleCommandLine
(
InstanceService
,
InstanceService
,
serviceClassName
,
serviceClassName
,
argv
=
argv
,
argv
=
argv
,
)
)
self
.
InstanceClass
=
InstanceService
self
.
InstanceClass
=
InstanceService
return
err
return
err
return
inner
return
inner
def
string_list
(
arg
):
def
string_list
(
arg
):
return
arg
.
split
()
return
arg
.
split
()
def
quote_command
(
command
):
def
quote_command
(
command
):
print
" "
.
join
(
command
)
print
(
" "
.
join
(
command
)
)
# Quote the program name, so it works even if it contains spaces
# Quote the program name, so it works even if it contains spaces
command
=
" "
.
join
([
'"%s"'
%
x
for
x
in
command
])
command
=
" "
.
join
([
'"%s"'
%
x
for
x
in
command
])
if
WIN
:
if
WIN
:
...
@@ -106,15 +112,15 @@ def quote_command(command):
...
@@ -106,15 +112,15 @@ def quote_command(command):
command
=
'"%s"'
%
command
command
=
'"%s"'
%
command
return
command
return
command
class
ZopeCtlOptions
(
ZDOptions
):
class
ZopeCtlOptions
(
ZDOptions
):
# Zope controller options.
# Zope controller options.
#
#
# After initialization, this should look very much like a
# After initialization, this should look very much like a
# zdaemon.zdctl.ZDCtlOptions instance. Many of the attributes are
# zdaemon.zdctl.ZDCtlOptions instance. Many of the attributes are
# initialized from different sources, however.
# initialized from different sources, however.
__doc__
=
__doc__
__doc__
=
__doc__
positional_args_allowed
=
1
positional_args_allowed
=
1
schemadir
=
os
.
path
.
dirname
(
Zope2
.
Startup
.
__file__
)
schemadir
=
os
.
path
.
dirname
(
Zope2
.
Startup
.
__file__
)
...
@@ -124,16 +130,16 @@ class ZopeCtlOptions(ZDOptions):
...
@@ -124,16 +130,16 @@ class ZopeCtlOptions(ZDOptions):
# this indicates that no explict program has been provided.
# this indicates that no explict program has been provided.
# the command line option can set this.
# the command line option can set this.
program
=
None
program
=
None
# this indicates that no explict socket name has been provided.
# this indicates that no explict socket name has been provided.
# the command line option can set this.
# the command line option can set this.
sockname
=
None
sockname
=
None
# XXX Suppress using Zope's <eventlog> section to avoid using the
# XXX Suppress using Zope's <eventlog> section to avoid using the
# same logging for zdctl as for the Zope appserver. There still
# same logging for zdctl as for the Zope appserver. There still
# needs to be a way to set a logfile for zdctl.
# needs to be a way to set a logfile for zdctl.
logsectionname
=
None
logsectionname
=
None
def
__init__
(
self
):
def
__init__
(
self
):
ZDOptions
.
__init__
(
self
)
ZDOptions
.
__init__
(
self
)
self
.
add
(
"program"
,
"runner.program"
,
"p:"
,
"program="
,
self
.
add
(
"program"
,
"runner.program"
,
"p:"
,
"program="
,
...
@@ -153,6 +159,8 @@ class ZopeCtlOptions(ZDOptions):
...
@@ -153,6 +159,8 @@ class ZopeCtlOptions(ZDOptions):
self
.
add
(
"umask"
,
"runner.umask"
,
"m:"
,
"umask="
)
self
.
add
(
"umask"
,
"runner.umask"
,
"m:"
,
"umask="
)
self
.
add
(
"sockname"
,
"runner.socket_name"
,
"s:"
,
"socket-name="
,
self
.
add
(
"sockname"
,
"runner.socket_name"
,
"s:"
,
"socket-name="
,
existing_dirpath
,
default
=
None
)
existing_dirpath
,
default
=
None
)
self
.
add
(
"transcript"
,
"runner.transcript"
,
"t:"
,
"transcript="
,
default
=
"/dev/null"
)
def
realize
(
self
,
*
args
,
**
kw
):
def
realize
(
self
,
*
args
,
**
kw
):
ZDOptions
.
realize
(
self
,
*
args
,
**
kw
)
ZDOptions
.
realize
(
self
,
*
args
,
**
kw
)
...
@@ -230,19 +238,19 @@ class ZopeCmd(ZDCmd):
...
@@ -230,19 +238,19 @@ class ZopeCmd(ZDCmd):
args
=
[
opt
,
svalue
]
args
=
[
opt
,
svalue
]
return
args
return
args
#
#
START OF WINDOWS ONLY STUFF
# START OF WINDOWS ONLY STUFF
if
WIN
:
if
WIN
:
def
get_service_name
(
self
):
def
get_service_name
(
self
):
return
'Zope'
+
str
(
hash
(
self
.
options
.
directory
.
lower
()))
return
'Zope'
+
str
(
hash
(
self
.
options
.
directory
.
lower
()))
def
get_status
(
self
):
def
get_status
(
self
):
sn
=
self
.
get_service_name
()
sn
=
self
.
get_service_name
()
try
:
try
:
stat
=
win32serviceutil
.
QueryServiceStatus
(
sn
)[
1
]
stat
=
win32serviceutil
.
QueryServiceStatus
(
sn
)[
1
]
self
.
zd_up
=
1
self
.
zd_up
=
1
except
pywintypes
.
error
,
err
:
except
pywintypes
.
error
as
err
:
if
err
[
0
]
==
1060
:
if
err
[
0
]
==
1060
:
# Service not installed
# Service not installed
stat
=
win32service
.
SERVICE_STOPPED
stat
=
win32service
.
SERVICE_STOPPED
...
@@ -252,59 +260,61 @@ class ZopeCmd(ZDCmd):
...
@@ -252,59 +260,61 @@ class ZopeCmd(ZDCmd):
self
.
zd_pid
=
(
stat
==
win32service
.
SERVICE_RUNNING
)
and
-
1
or
0
self
.
zd_pid
=
(
stat
==
win32service
.
SERVICE_RUNNING
)
and
-
1
or
0
self
.
zd_status
=
"args=%s"
%
self
.
options
.
program
self
.
zd_status
=
"args=%s"
%
self
.
options
.
program
do_start
=
do_windows
(
'start'
)
do_start
=
do_windows
(
'start'
)
do_stop
=
do_windows
(
'stop'
)
do_stop
=
do_windows
(
'stop'
)
do_restart
=
do_windows
(
'restart'
)
do_restart
=
do_windows
(
'restart'
)
# Add extra commands to install and remove the Windows service
# Add extra commands to install and remove the Windows service
def
do_install
(
self
,
arg
):
def
do_install
(
self
,
arg
):
err
=
do_windows
(
'install'
)(
self
,
arg
)
err
=
do_windows
(
'install'
)(
self
,
arg
)
if
not
err
:
if
not
err
:
# If we installed successfully, put info in registry for the
# If we installed successfully, put info in registry for the
# real Service class to use:
# real Service class to use:
command
=
'"%s" -C "%s"'
%
(
command
=
'"%s" -C "%s"'
%
(
# This gives us the instance script for buildout instances
# This gives us the instance script for buildout instances
# and the install script for classic instances.
# and the install script for classic instances.
os
.
path
.
join
(
os
.
path
.
split
(
sys
.
argv
[
0
])[
0
],
'runzope'
),
os
.
path
.
join
(
os
.
path
.
split
(
sys
.
argv
[
0
])[
0
],
'runzope'
),
self
.
options
.
configfile
self
.
options
.
configfile
)
)
self
.
InstanceClass
.
setReg
(
'command'
,
command
)
self
.
InstanceClass
.
setReg
(
'command'
,
command
)
# This is unfortunately needed because runzope.exe is a setuptools
# This is unfortunately needed because runzope.exe is a
# generated .exe that spawns off a sub process, so pid would give us
# setuptools generated .exe that spawns off a sub process,
# the wrong event name.
# so pid would give us the wrong event name.
self
.
InstanceClass
.
setReg
(
'pid_filename'
,
self
.
options
.
configroot
.
pid_filename
)
self
.
InstanceClass
.
setReg
(
'pid_filename'
,
self
.
options
.
configroot
.
pid_filename
)
return
err
return
err
def
help_install
(
self
):
def
help_install
(
self
):
print
"install -- Installs Zope as a Windows service."
print
(
"install -- Installs Zope as a Windows service."
)
do_remove
=
do_windows
(
'remove'
)
do_remove
=
do_windows
(
'remove'
)
def
help_remove
(
self
):
def
help_remove
(
self
):
print
"remove -- Removes the Zope Windows service."
print
(
"remove -- Removes the Zope Windows service."
)
do_windebug
=
do_windows
(
'debug'
)
do_windebug
=
do_windows
(
'debug'
)
def
help_windebug
(
self
):
def
help_windebug
(
self
):
print
"windebug -- Runs the Zope Windows service in the foreground, in debug mode."
print
(
"windebug -- Runs the Zope Windows service "
"in the foreground, in debug mode."
)
# END OF WINDOWS ONLY STUFF
## END OF WINDOWS ONLY STUFF
def
get_startup_cmd
(
self
,
python
,
more
):
def
get_startup_cmd
(
self
,
python
,
more
):
cmdline
=
(
'%s -c "from Zope2 import configure;'
cmdline
=
(
'%s -c "from Zope2 import configure;'
'configure(%r);'
%
'configure(%r);'
%
(
python
,
self
.
options
.
configfile
)
(
python
,
self
.
options
.
configfile
)
)
)
return
cmdline
+
more
+
'
\
"
'
return
cmdline
+
more
+
'
\
"
'
def
do_debug
(
self
,
arg
):
def
do_debug
(
self
,
arg
):
cmdline
=
self
.
get_startup_cmd
(
self
.
options
.
python
+
' -i'
,
cmdline
=
self
.
get_startup_cmd
(
self
.
options
.
python
+
' -i'
,
'import Zope2; app=Zope2.app()'
)
'import Zope2; app=Zope2.app()'
)
print
(
'Starting debugger (the name "app" is bound to the top-level '
print
(
'Starting debugger (the name "app" is bound to the top-level '
'Zope object)'
)
'Zope object)'
)
os
.
system
(
cmdline
)
os
.
system
(
cmdline
)
def
do_foreground
(
self
,
arg
):
def
do_foreground
(
self
,
arg
):
...
@@ -321,30 +331,34 @@ class ZopeCmd(ZDCmd):
...
@@ -321,30 +331,34 @@ class ZopeCmd(ZDCmd):
except
KeyboardInterrupt
:
except
KeyboardInterrupt
:
pass
pass
finally
:
finally
:
for
addition
in
local_additions
:
program
.
remove
(
addition
)
for
addition
in
local_additions
:
program
.
remove
(
addition
)
def
help_debug
(
self
):
def
help_debug
(
self
):
print
"debug -- run the Zope debugger to inspect your database"
print
(
"debug -- run the Zope debugger to inspect your database"
)
print
" manually using a Python interactive shell"
print
(
" manually using a Python interactive shell"
)
def
__getattr__
(
self
,
name
):
def
__getattr__
(
self
,
name
):
"""Getter to check if an unknown command is implement by an entry point."""
"""
Getter to check if an unknown command is implement by an entry point.
"""
if
not
name
.
startswith
(
"do_"
):
if
not
name
.
startswith
(
"do_"
):
raise
AttributeError
(
name
)
raise
AttributeError
(
name
)
data
=
list
(
pkg_resources
.
iter_entry_points
(
"zopectl.command"
,
name
=
name
[
3
:]))
data
=
list
(
pkg_resources
.
iter_entry_points
(
"zopectl.command"
,
name
=
name
[
3
:]))
if
not
data
:
if
not
data
:
raise
AttributeError
(
name
)
raise
AttributeError
(
name
)
if
len
(
data
)
>
1
:
if
len
(
data
)
>
1
:
print
>>
sys
.
stderr
,
"Warning: multiple entry points found for command"
sys
.
stderr
.
write
(
"Warning: multiple entry points found for command"
)
return
return
func
=
data
[
0
].
load
()
func
=
data
[
0
].
load
()
if
not
callable
(
func
):
if
not
callable
(
func
):
print
>>
sys
.
stderr
,
"Error: %s is not a callable method"
%
name
sys
.
stderr
.
write
(
"Error: %s is not a callable method"
%
name
)
return
return
return
self
.
run_entrypoint
(
data
[
0
])
return
self
.
run_entrypoint
(
data
[
0
])
def
run_entrypoint
(
self
,
entry_point
):
def
run_entrypoint
(
self
,
entry_point
):
def
go
(
arg
):
def
go
(
arg
):
# If the command line was something like
# If the command line was something like
...
@@ -366,9 +380,9 @@ class ZopeCmd(ZDCmd):
...
@@ -366,9 +380,9 @@ class ZopeCmd(ZDCmd):
tup
=
csv
.
reader
(
tup
,
delimiter
=
' '
).
next
()
tup
=
csv
.
reader
(
tup
,
delimiter
=
' '
).
next
()
# Remove -c and add command name as sys.argv[0]
# Remove -c and add command name as sys.argv[0]
cmd
=
[
'import sys'
,
cmd
=
[
'import sys'
,
'sys.argv.pop()'
,
'sys.argv.pop()'
,
'sys.argv.append(r
\
'
%s
\
'
)'
%
entry_point
.
name
'sys.argv.append(r
\
'
%s
\
'
)'
%
entry_point
.
name
]
]
if
len
(
tup
)
>
1
:
if
len
(
tup
)
>
1
:
argv
=
tup
[
1
:]
argv
=
tup
[
1
:]
...
@@ -377,53 +391,55 @@ class ZopeCmd(ZDCmd):
...
@@ -377,53 +391,55 @@ class ZopeCmd(ZDCmd):
cmd
.
extend
([
cmd
.
extend
([
'import pkg_resources'
,
'import pkg_resources'
,
'import Zope2'
,
'import Zope2'
,
'func=pkg_resources.EntryPoint.parse(
\
'
%s
\
'
).load(False)'
%
entry_point
,
'func=pkg_resources.EntryPoint.parse(
\
'
%s
\
'
).load(False)'
%
entry_point
,
'app=Zope2.app()'
,
'app=Zope2.app()'
,
'func(app, sys.argv[1:])'
,
'func(app, sys.argv[1:])'
,
])
])
cmdline
=
self
.
get_startup_cmd
(
self
.
options
.
python
,
' ; '
.
join
(
cmd
))
cmdline
=
self
.
get_startup_cmd
(
self
.
options
.
python
,
' ; '
.
join
(
cmd
))
self
.
_exitstatus
=
os
.
system
(
cmdline
)
self
.
_exitstatus
=
os
.
system
(
cmdline
)
return
go
return
go
def
do_run
(
self
,
args
):
def
do_run
(
self
,
args
):
if
not
args
:
if
not
args
:
print
"usage: run <script> [args]"
print
(
"usage: run <script> [args]"
)
return
return
# replace sys.argv
# replace sys.argv
script
=
args
.
split
(
' '
)[
0
]
script
=
args
.
split
(
' '
)[
0
]
cmd
=
(
cmd
=
(
"import sys; sys.argv[:]=%r.split(' ');"
"import sys; sys.argv[:]=%r.split(' ');"
"import Zope2; app=Zope2.app(); execfile(%r)"
"import Zope2; app=Zope2.app(); execfile(%r)"
)
%
(
args
,
script
)
)
%
(
args
,
script
)
cmdline
=
self
.
get_startup_cmd
(
self
.
options
.
python
,
cmd
)
cmdline
=
self
.
get_startup_cmd
(
self
.
options
.
python
,
cmd
)
self
.
_exitstatus
=
os
.
system
(
cmdline
)
self
.
_exitstatus
=
os
.
system
(
cmdline
)
def
help_run
(
self
):
def
help_run
(
self
):
print
"run <script> [args] -- run a Python script with the Zope "
print
(
"run <script> [args] -- run a Python script with the Zope "
)
print
" environment set up. The script can use "
print
(
" environment set up. The script can use "
)
print
" the name 'app' access the top-level Zope"
print
(
" the name 'app' access the top-level "
)
print
" object"
print
(
" Zope object"
)
def
do_adduser
(
self
,
arg
):
def
do_adduser
(
self
,
arg
):
try
:
try
:
name
,
password
=
arg
.
split
()
name
,
password
=
arg
.
split
()
except
:
except
Exception
:
print
"usage: adduser <name> <password>"
print
(
"usage: adduser <name> <password>"
)
return
return
cmdline
=
self
.
get_startup_cmd
(
cmdline
=
self
.
get_startup_cmd
(
self
.
options
.
python
,
self
.
options
.
python
,
'import Zope2; '
'import Zope2; '
'app = Zope2.app(); '
'app = Zope2.app(); '
'result = app.acl_users._doAddUser(
\
'
%s
\
'
,
\
'
%s
\
'
, [
\
'
Manager
\
'
], []); '
'result = app.acl_users._doAddUser('
'
\
'
%s
\
'
,
\
'
%s
\
'
, [
\
'
Manager
\
'
], []); '
'import transaction; '
'import transaction; '
'transaction.commit(); '
'transaction.commit(); '
'print
\
'
Created user:
\
'
, result'
'print
\
'
Created user:
\
'
, result'
)
%
(
name
,
password
)
)
%
(
name
,
password
)
os
.
system
(
cmdline
)
os
.
system
(
cmdline
)
def
help_adduser
(
self
):
def
help_adduser
(
self
):
print
"adduser <name> <password> -- add a Zope management user"
print
(
"adduser <name> <password> -- add a Zope management user"
)
def
main
(
args
=
None
):
def
main
(
args
=
None
):
...
@@ -439,19 +455,23 @@ def main(args=None):
...
@@ -439,19 +455,23 @@ def main(args=None):
options
.
interactive
=
1
options
.
interactive
=
1
if
options
.
interactive
:
if
options
.
interactive
:
try
:
try
:
import
readline
import
readline
# NOQA
except
ImportError
:
except
ImportError
:
pass
pass
print
"program:"
,
" "
.
join
(
options
.
program
)
print
(
"program:"
+
" "
.
join
(
options
.
program
)
)
c
.
do_status
()
c
.
do_status
()
c
.
cmdloop
()
c
.
cmdloop
()
else
:
else
:
return
min
(
c
.
_exitstatus
,
1
)
return
min
(
c
.
_exitstatus
,
1
)
def
_ignoreSIGCHLD
(
*
unused
):
def
_ignoreSIGCHLD
(
*
unused
):
while
1
:
while
1
:
try
:
os
.
waitpid
(
-
1
,
os
.
WNOHANG
)
try
:
except
OSError
:
break
os
.
waitpid
(
-
1
,
os
.
WNOHANG
)
except
OSError
:
break
def
run
():
def
run
():
# we don't care to be notified of our childrens' exit statuses.
# we don't care to be notified of our childrens' exit statuses.
...
@@ -461,10 +481,10 @@ def run():
...
@@ -461,10 +481,10 @@ def run():
# Any signals set to be caught by the calling process are reset
# Any signals set to be caught by the calling process are reset
# to their default behaviour.
# to their default behaviour.
# The SIGCHLD signal (when set to SIG_IGN) may or may not be reset
# The SIGCHLD signal (when set to SIG_IGN) may or may not be reset
# to SIG_DFL.
# to SIG_DFL.
# If it is not reset, 'os.wait[pid]' can non-deterministically fail.
# If it is not reset, 'os.wait[pid]' can non-deterministically fail.
# Thus, use a way such that "SIGCHLD" is definitely reset in children.
# Thus, use a way such that "SIGCHLD" is definitely reset in children.
#signal.signal(signal.SIGCHLD, signal.SIG_IGN)
#
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
if
not
WIN
and
os
.
uname
()[
0
]
!=
'Darwin'
:
if
not
WIN
and
os
.
uname
()[
0
]
!=
'Darwin'
:
# On Windows the os.uname method does not exist.
# On Windows the os.uname method does not exist.
# On Mac OS X, setting up a signal handler causes waitpid to
# On Mac OS X, setting up a signal handler causes waitpid to
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment