Plone评估员无法找到对象

时间:2015-01-09 17:09:52

标签: plone plone-4.x

背景: 同事复制了一个站点,然后通过复制和粘贴在ZMI中重命名。该网站的客户随后将其中一个网站改为中文版

所以我们在服务器上有这两个网站,一切都很好,花花公子,然后几个月前复制的网站停止工作,所有网址都带来了这个错误http://echinaapple-cn.ucdavis.edu,而不是“copy_of_apple-check”这是一个不同的价值。

我在复制的网站上进入zmi撤消,但找不到任何包含该变量的内容。然后我转到原始站点(即从zmi undo中复制),发现其中一个用户删除了一个具有该名称的页面。我恢复了这个改变并且神奇地复制了复制的网站。

所以现在我在同一条船上,我看到2014年12月24日的行动从copy_of_apple-check重命名了一些东西。这次问题是当我尝试撤消plone时给出了一个错误,说“有些数据被后来的事务修改了撤消错误”

以下是ZMI撤消中唯一具有copy_of_apple-check

的操作
/ChinaApple/folder_rename_form
Renamed ['/ChinaApple/dwarf-orchard-management/elearning/copy5_of_irrigation-of-high-density-orchards', '/ChinaApple/dwarf-orchard-management/elearning/copy_of_irrigation-of-high-density-orchards', '/ChinaApple/dwarf-orchard-management/elearning/copy4_of_irrigation-of-high-density-orchards', '/ChinaApple/dwarf-orchard-management/elearning/copy2_of_irrigation-of-high-density-orchards', '/ChinaApple/dwarf-orchard-management/elearning/copy3_of_irrigation-of-high-density-orchards', '/ChinaApple/dwarf-orchard-management/elearning/copy_of_apple-check'] by ChinaApple nmmadden

我们无法弄清楚的最重要的事情之一就是为什么原始网站仍然会影响复制的网站,以及如何修复血腥的东西。

我们都试图在谷歌上发现类似的错误但无济于事。

我们尝试过的事情:

  1. 使用相同的网址在原始网站的同一位置添加页面

  2. 还原多行

  3. 删除中文版zmi中的copy_of_apple-check(给出了大错误)

  4. 我们无法恢复服务器,因为我们只有三天前

    如果你们听说过这个或者有任何想法,请告诉我,否则感谢您的时间!

    原始网站: http:// echinaapple.ucdavis.edu

    复制无法访问的网站: http:// echinaapple-cn.ucdavis.edu

2 个答案:

答案 0 :(得分:0)

也许我可以帮助。

您可以随时在12月24日的适当时间截断ZODB:这当然意味着您将丢失对工作站点的任何后续更改(显然,对其他站点不会有任何更改)。

您可以在12/24之后确定工作站点上的更改,导出它,并在截断后重新导入。

然后你需要完全分开两个站点,分开ZODB,最好是单独的ZOPE服务器,以确保不会再发生这种情况。我将导出所有中文内容并导入新的Plone网站。

这是我使用的脚本:它依赖于使用 collective.recipe.backup 进行常规备份的buildout配置,但您应该能够插入任何ZODB文件作为输入(它可能最简单,但要将 collective.recipe.backup 添加到buildout,重新运行buildout,在现有ZODB上运行备份,然后运行此脚本。

无论如何,首先保存您当前ZODB的副本!

#! /usr/bin/python2.6 zopepy

# Standalone usage:
# cd to the directory containing this script, then
#  HTTP_REFERER=anything ./restoreDB.py yyyy-mm-dd [hh:mm:ss]
#
# The HTTP_REFERER environment variable needs to be set to any non-null value
# to make the script think it's being called in a CGI setting
# The arguments are a date/time stamp in Local time.

import cgi
import cgitb
import datetime
import time
from dateutil import tz
from dateutil.parser import parse as date_parse
import logging
import os
import re
import subprocess
from subprocess import PIPE
import sys
import ConfigParser
from ZODB.FileStorage import FileIterator
from ZODB.TimeStamp import TimeStamp as ZODBTimeStamp
cgitb.enable()
zeo = ''
loglevel = logging.INFO
logging.basicConfig(filename='/tmp/recover.log',level=loglevel,
    format='%(asctime)s %(levelname)s: %(message)s')

def restartZeo():
    subprocess.check_call([zeo, 'start chone-zeo'])

def execute(cmd, stdin='', shell=False):
    proc = subprocess.Popen(cmd, stdin = PIPE, stdout = PIPE, stderr= subprocess.STDOUT, shell=shell)
    output, error = proc.communicate(input=stdin)
    logging.info(cmd)
    logging.info(output)
    if proc.returncode > 0:
        restartZeo()
        print "\n"
        raise Exception("Aborted")
    return output

def start():
    print "Content-type: text/html"

    global zeo
    form = cgi.FieldStorage()
    logging.info(form)
    restore_date = date_parse(form.getfirst('restore-to-time', ''))
    restore_date = restore_date.replace(second=59,tzinfo=tz.tzlocal()).astimezone(tz.tzoffset(None, 0))
    logging.info('restore_date: %s' % restore_date)

    referer = os.environ.get('HTTP_REFERER','')
    if not referer:
        print "\n"
        raise Exception('HTTP_REFERER (%s) does not appear to be part of the Plone site' % referer)

    # read the buildout's .installed.cfg file
    config = ConfigParser.ConfigParser()
    config.readfp(open('../.installed.cfg'))
    # get the path to the backup command
    try:
        paths = re.split(r'\s+',config.get('backup','__buildout_installed__'))
        backup= [x for x in paths if x.endswith('/backup')][0]
    except:
        print "\n"
        raise Exception("Can't find the path to the backup command")
    bin = os.path.dirname(backup)
    site= bin.split(os.sep)[-2].split('-')[-1]

    stopped = False
    # shutdown the ZEO before we start the recovery
    # we try to do it from the parent directory's "supervisorctl", otherwise directly 
    # from the local zeoserver command
    for cmd in ['/../../bin/supervisorctl','/zeoserver']:
        zeo = bin+cmd
        try:
            subprocess.check_call([zeo, 'stop %s-zeo' % site])
            stopped = True
            break
        except:
            pass

    if not stopped:
        print "\n"
        raise Exception("Could not stop the ZEO server.")

    # get the path to the Data.fs
    db = config.get('backup','datafs')

    # determine the first backup FOLLOWING the time given 
    repozo_date = restore_date.strftime('%Y-%m-%d-%H-%M-%S')
    logging.info('repozo_date: '+repozo_date)
    backup_path = config.get('backup','location')
    logging.info('backup_path: '+backup_path)
    # get the list of backups (most recent first)
    files = [x for x in sorted(os.listdir(backup_path),reverse=True) 
             if x.endswith('sz') and x > repozo_date]

    # take a backup before we start, but only if:
    # - there is no backup containing the repozo_date or,
    # - the latest backup is older than the current db
    # this prevents dropping our last full backup off the cycle when we
    # immediately decide to restore the original file after a previous restore
    current_ts=time.gmtime(os.path.getmtime(db)) # the modification timestamp of the current database
    if len(files) == 0 or files[0] < time.strftime('%Y-%m-%d-%H-%M-%S',current_ts):
        execute([backup])
    # if we found an older backup we need restored:
    if len(files) > 0:
        # do a restore to the end of the first backup after the time we really want
        repozo_date = files[-1].split('.')[0]
        logging.info('repozo_date: '+repozo_date)

        output = execute([bin+'/restore', repozo_date], stdin='yes\n\n\n')
        for line in output.splitlines():
            if 'restoring database file' in line:
                db = line.split(' to ')[1]
                break

    # find the next transaction after our timestamp
    ts  = list(restore_date.timetuple())[:6]
    tid = repr(ZODBTimeStamp(*ts))
    it  = FileIterator(db, tid)
    f   = open(db, 'r+b')
    # truncate the database at that transaction
    logging.info('truncating db at %d' % it._pos)
    f.seek(it._pos)
    f.truncate()
    f.close()

    # restart the zeo
    execute([zeo, 'restart %(site)s-zeo %(site)s-plone' % locals()])
    # redirect to the Restore page
    print "Location: %s\n" % referer

if __name__ == '__main__':
    from optparse import OptionParser
    parser = OptionParser()
    (options, args) = parser.parse_args()
    os.environ['QUERY_STRING'] = "restore-to-time=%s" % ' '.join(args)
    start()

答案 1 :(得分:0)

我能够通过返回并将内容添加到同一位置的旧网站来解决此问题。

我没有必要使用你的脚本Auspex!