【问题标题】:PHP LFTP data mirror outputPHP LFTP数据镜像输出
【发布时间】:2013-01-07 15:28:16
【问题描述】:

我使用的是 Linux 本地计算机,需要定期备份/镜像一些非常大的文件结构。我只能访问 SFTP。

我追求的是简单的一键式解决方案。我最初尝试在 BASH 中编写这个小脚本,但我以前从未使用过它,并且对语法不熟悉,所以我求助于 PHP。 (我确实明白 PHP 不是为这类工作而设计的,但我时间紧迫,没有时间进入 BASH atm)

<?php
//init
parse_str(implode('&', array_slice($argv, 1)), $_GET);
$error = array();

$lPrefix         = '/home/hozza/Sites/';
$archiveLocation = '/home/hozza/Backups/';

$lDir = isset($_GET['l']) ? $_GET['l'] : $error[] = 'Local Directory Required';
$rDir = isset($_GET['r']) ? $_GET['r'] : $error[] = 'Remote Directory Required';
$bookmark = isset($_GET['b']) ? $_GET['b'] : $error[] = 'lftp Bookmark Required';

//Check for args
if(count($error) == 0) {
    $archiveName = end(explode('/', $lDir)) . '_' . date('Y-m-d_H-i');

    //Validate local dir
    if(is_dir($lPrefix . $lDir)) {

        //preserve Sublime Text 2 config SFTP files
        $ST2_SFTP_conf = false;
        if(file_exists($lPrefix . $lDir . '/sftp-config.json')) {
            $ST2_SFTP_conf = file_get_contents($lPrefix . $lDir . '/sftp-config.json');
            unlink($lPrefix . $lDir . '/sftp-config.json');
        }

        //Start mirror
        $lftOutput = explode("\n", shell_exec('lftp -e "mirror -e -p --parallel=10 --log=' . $archiveLocation . 'logs/' . $archiveName . '.txt ' . $rDir . '/ ' . $lPrefix . $lDir . '/; exit top" ' . $bookmark));

        //Tar regardless of lftp error or success
        $tarOutput = shell_exec('cd ' . $lPrefix . ' && tar -czf ' . $archiveLocation . $archiveName . '.tar.gz ' . $lDir);

        //Output completion or errors
        shell_exec('notify-send -i gnome-network-properties -t 0 "Mirror & Archive Complete" "' . $archiveName . '\n\n' . implode('\n', $lftOutput) . $tarOutput . '"');

        //put back ST2 SFTP conf
        if($ST2_SFTP_conf != false) file_put_contents($lPrefix . $lDir . '/sftp-config.json', $ST2_SFTP_conf);

        exit;
    }
    else shell_exec('notify-send -i error -t 0 "Mirror & Archive Error" "' . date('Y-m-d') . ' ' . date('H-i') . '\n' . $lDir . ' \n Does not exist! D:"');
}
else shell_exec('notify-send -i error -t 0 "Mirror & Archive Error" "' . date('Y-m-d') . ' ' . date('H-i') . '\n' . implode('\n', $error) . '"');
?>

它可以通过这样的快捷方式在许多网站上运行...

terminator -T "Mirror & Archive" -e "php ~/Programs/mirror.php l=local-dir_path r=./ b=lftp-bookmark-name"

如果 LFTP 书签中没有密码(不应该因为它以纯文本形式存储),终端会提示输入密码,脚本运行后,会给出一个很好的通知,其中包含有关文件/文件夹/的一些信息速度等。

但是,当脚本在终端中运行时,只有“输入密码”位输出到终端,我希望终端中显示所有输出(通常会显示当前正在使用的文件/文件夹等等)

有人知道怎么做吗?

【问题讨论】:

  • 也许您应该从您的shell_exec() 调用中捕获/输出返回值?但是,这只会在命令完全完成之后显示输出。您编写脚本的方式我认为您永远无法看到它的现场直播。
  • 是的 atm 它会输出最终结果,但我可能无法像这样。对于如何更好地应对这种情况,您有什么建议吗?

标签: php file-structure bash ftp


【解决方案1】:

IIRC 你看到密码提示输出到终端的原因是它正在使用stderr。您可以尝试将 stdout 重定向到 stderr 以获取应显示“实时”进度的命令。将此添加到 shell_exec() 命令的末尾:1&gt;&amp;2

即:

shell_exec('lftp -e "mirror -e -p --parallel=10 --log=' . $archiveLocation . 'logs/' . $archiveName . '.txt ' . $rDir . '/ ' . $lPrefix . $lDir . '/; exit top" ' . $bookmark . ' 1>&2')

但是,这将使您无法获得 shell_exec 返回的任何内容以用于记录目的。我的建议是这样的:

$log_stem = '/tmp/' . time() . '_';  // ie: /tmp/1357581737_
$lfOutfile = $log_stem . 'lftp.log';
$tarOutfile = $log_stem . 'tar.log';

shell_exec('lftp -blah | tee ' . $lfOutfile ' 1>&2' );
shell_exec('tar -blah | tee ' . $tarOutfile ' 1>&2' );

$lfOut = file_get_contents($lfOutfile);
$tarOut = file_get_contetns(tarOutfile);

// remove tmp files
unlink($lfOutfile);
unlink($tarOutfile);

这会在将输出重定向到 stderr 之前将输出的副本捕获到文件中,以便您可以实时观看。

但是,如果您想通过 cron 运行它,我建议反对向 stderr 写入任何不是错误的内容,否则 cron 将在每次运行时发送警告电子邮件。

【讨论】:

  • 我试过了,但它不起作用......脚本做得很好,但它仍然没有输出到终端。 pastebin.com/zCeNvK1s
【解决方案2】:

我认为最后一个答案很接近:

要么:

shell_exec('lftp -blah |& tee ' . $lfOutfile );
shell_exec('tar -blah |& tee ' . $tarOutfile );

如果还是不行,试试这个:

shell_exec('lftp -blah 2>&1 | tee ' . $lfOutfile );
shell_exec('tar -blah 2>&1 | tee ' . $tarOutfile );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多