ความเสียหายภายในปฏิทิน: ซ้ำกัน จะวิเคราะห์สาเหตุและแก้ไขได้อย่างไร


1

ฉันใช้CalendarMac ที่ใช้ MacOS X Mountain Lion (10.8.5)

Mac เครื่องนี้ทำข้อมูลให้ตรงกันกับ iPhone ที่ใช้ iOS 7.1.2 เป็นประจำอย่างสม่ำเสมอ

นี่Calendarคือการจัดเก็บ 15 ปีของเหตุการณ์ที่จัดขึ้นภายใน 9 "ปฏิทิน" เนื่องจากข้อมูลบางส่วนมีความอ่อนไหวสูงเป็นมืออาชีพหรือเป็นส่วนตัวฉันจึงไม่ซิงโครไนซ์ข้อมูลเหล่านั้นในปฏิทินสาธารณะในรูปแบบใด ๆ ( iCloud, Google Calendar... ) ในทางกลับกันฉันมีการTime Machineสำรองข้อมูลจำนวนมากและการสำรองข้อมูลเต็มรูปแบบ

เมื่อเร็ว ๆ นี้ฉันค้นพบค่อนข้างคาดไม่ถึงว่าตั้งแต่ฤดูร้อนปี 2544 ฉันได้ทำซ้ำกิจกรรมเต็มวันภายในCalendarบน Mac ของฉัน ฉันสามารถเห็นสิ่งเหล่านี้ได้อย่างรวดเร็วเนื่องจากลักษณะที่ซ้ำกันของพวกเขาสามารถมองเห็นได้โดยตรง นี่ไม่ใช่กรณีทั่วไป: กิจกรรมเต็มวันส่วนใหญ่ของฉันไม่ซ้ำกัน แต่ "ปฏิทิน" 9 รายการทั้งหมดของฉันได้รับผลกระทบจากความเสียหายนี้ ฉันประเมินว่าฉันมีเหตุการณ์ประมาณสองสามร้อยเหตุการณ์ในกรณีนี้ ฉันเห็นความเสียหายแบบเดียวกันบน iPhone ของฉัน


ฉันส่งออกหนึ่งในปฏิทินของฉันและแยกหนึ่งในรายการที่ซ้ำกัน นี่คือผลลัพธ์ของ diff บน.icsสารสกัด2 ตัว:

••My_Mac••$ diff duplicate.[12].ics
2c2
< UID:74FC7CC1-016C-4A74-9E02-7ECDD82C8129
---
> UID:9B6BC4CD-5859-4DC2-8DEA-9158CB8F9B0D
10,11c10,11
< X-WR-ALARMUID:D0FE4A14-981C-4409-84C1-B11107F7EC31
< UID:D0FE4A14-981C-4409-84C1-B11107F7EC31
---
> X-WR-ALARMUID:48141767-C3C6-4131-9984-0DD080833D9F
> UID:48141767-C3C6-4131-9984-0DD080833D9F
••My_Mac••$

สัญกรณ์: ••ชื่อสตริง••หมายความว่า "ชื่อ" ถูก redacted

นี่คือสิ่งที่ฉันพบภายใน/var/log/system.logและที่อาจเกี่ยวข้อง:

13 ก.ย. 10:08:32 •• My_Mac •• SyncServer [93677]: [0x7fbe60c0bdd0] | SyncServer | คำเตือน | การรีเฟรชสุนัขเฝ้าบ้านเนื่องจากการแจ้งเตือนการเปลี่ยนแปลงเวลาในปฏิทิน
13 ก.ย. 16:09:10 •• My_Mac •• SyncServer [94189]: [0x7fd25a40bdd0] | SyncServer | คำเตือน | การรีเฟรชสุนัขเฝ้าบ้านเนื่องจากการแจ้งเตือนการเปลี่ยนแปลงเวลาในปฏิทิน
14 ก.ย. 03:21:15 •• My_Mac •• SyncServer [94351]: [0x7f9e1ac0bdd0] | SyncServer | คำเตือน | การรีเฟรชสุนัขเฝ้าบ้านเนื่องจากการแจ้งเตือนการเปลี่ยนแปลงเวลาในปฏิทิน
14 ก.ย. 08:56:41 •• My_Mac •• SyncServer [94351]: [0x7f9e1ac0bdd0] | SyncServer | คำเตือน | การรีเฟรชสุนัขเฝ้าบ้านเนื่องจากการแจ้งเตือนการเปลี่ยนแปลงเวลาในปฏิทิน
15 กันยายน 14:11:39 •• My_Mac •• SyncServer [94351]: [0x7f9e1ac0bdd0] | SyncServer | คำเตือน | การรีเฟรชสุนัขเฝ้าบ้านเนื่องจากการแจ้งเตือนการเปลี่ยนแปลงเวลาในปฏิทิน
16 ก.ย. 00:25:17 •• My_Mac •• SyncServer [95764]: [0x7faf92c0bdd0] | SyncServer | คำเตือน | การรีเฟรชสุนัขเฝ้าบ้านเนื่องจากการแจ้งเตือนการเปลี่ยนแปลงเวลาในปฏิทิน
16 ก.ย. 13:36:27 •• My_Mac •• SyncServer [96213]: [0x7f9470c0bdd0] | SyncServer | คำเตือน | การรีเฟรชสุนัขเฝ้าบ้านเนื่องจากการแจ้งเตือนการเปลี่ยนแปลงเวลาในปฏิทิน
16 ก.ย. 13:51:33 •• My_Mac •• CalendarAgent [90827]: ถ่าน _ สำหรับ PropertyName ไม่ถูกต้องในบรรทัด 7
16 ก.ย. 13:51:33 •• My_Mac •• CalendarAgent [90827]: EOF ที่ไม่คาดคิดกลับโทเค็นล่าสุดเป็นทางเลือก


ฉันจะวิเคราะห์ได้อย่างไรว่าเหตุการณ์ที่ซ้ำกันเหล่านี้มาจากที่ใด

ฉันจะหาวันที่และเวลาที่เหตุการณ์อาจเริ่มต้นการทุจริตในวาระของฉันได้อย่างไร หากไม่มีวันที่เริ่มต้นของความเสียหายการสำรองข้อมูลของฉันจะช่วยได้เล็กน้อย นอกจากนี้พวกเขาจะบ่งบอกถึงการรวมสร้างของเหตุการณ์ที่ถูกต้องซึ่งเกิดขึ้นหลังจากความเสียหาย

ฉันจะได้รับวิสัยทัศน์ที่ถูกต้องของการทุจริตของ "ปฏิทิน" ทั้งหมดของฉันนี้ได้อย่างไร

และนอกจากนี้ฉันจะแก้ไขความเสียหายของข้อมูลขนาดใหญ่และสุ่มนี้ได้อย่างไร

คำตอบ:


0

ฉันยังไม่ได้คำอธิบายที่ถูกต้องเกี่ยวกับการคอร์รัปชั่น แต่อย่างน้อยฉันก็เขียนวิธีแก้ปัญหาเพื่อให้มีการมองเห็นที่ชัดเจนถึงขอบเขตของความเสียหายและเพื่อแก้ไข

นี่คือสคริปต์ Perl duplicate.pl::

$ cat <<'eof' >duplicate.pl
#!/usr/bin/perl
use strict ;
use warnings ;

# program reading on its standard input a file under
# ics format exported by iCal or Calendar
# Both only export one calendar at a time

# file = name of created file for a given calendar

my %file = () ;

# filedesc = file descriptor of the created calendar file

my %filedesc = () ;

# hash of all unduplicated events local_event_id
my %events = () ;

# current event storage
my @event = () ;
my $dtstart = '' ;
my $dtend = '' ;

# number of events analysed
my $num_event = 0 ;
my $duplicate = 0 ;
my $calendar = '' ;

# state booleans
my $in_header = 1 ;
my $in_event = 0 ;
my $in_summary = 0 ;
my $line = '' ;
my $summary = '' ;

# local event identifier :      summary;dtstart;dtend
# because ';' is never used within a name
my $local_event_id = '' ;

while (<STDIN>) {
        $line = $_ ;

# header :      BEGIN:VCALENDAR
#               ...
#               BEGIN:VEVENT

        if ( $in_summary ) {

#               continuation line of summary

                if ( $line =~ /^ (.+)\r\n$/ ) {
                        $summary .= $1 ;
                } else {

#                       end of summary continuation lines analysis

                        $in_summary = 0 ;
                }
        }
        if ( $line =~ /^SUMMARY[^:]*:(.+)\r\n$/ ) {
                $summary = $1 ;
                $in_summary = 1 ;
        } elsif ( $line =~ /^BEGIN:VEVENT/) {
                if ( $in_header ) {
                        $in_header = 0 ;

#                       print every lines of event or header

                        foreach $line (@event) {
                                printf {$filedesc{$calendar}} "%s", $line ;
                        }
                }
                $in_event = 1 ;
                @event = () ;
        } elsif ( $line =~ /^X-WR-CALNAME:(.+)\r\n$/) {
                $calendar = $1 ;

#               create .ics file

                if ( ! defined $file{$calendar} ) {
                        $file{$calendar} = $calendar . ".ics" ;
                        if ( -e $file{$calendar} ) {
                                die "$file{$calendar} already exists\n" ;
                        }
                        open ($filedesc{$calendar}, ">", $file{$calendar}) ;

#                       print every lines of header

                        foreach $line (@event) {
                                printf {$filedesc{$calendar}} "%s", $line ;
                        }
                        @event = () ;
                        $in_event = 0 ;
                }
#               printf STDOUT "calendar = %s\n", $calendar ;
#               printf STDOUT "file = %s\n", $file{$calendar} ;
#               printf STDOUT "fh = %d\n", $filedesc{$calendar} ;

        } elsif ( $line =~ /^DTSTART[^:]*:(.*)\r\n$/ ) {
                $dtstart = $1 ;

#               printf STDOUT "DTSTART = %32s\n", $dtstart ;

        } elsif ( $line =~ /^DTEND[^:]*:(.*)\r\n$/ ) {
                $dtend = $1 ;

#               printf STDOUT "DTEND = %32s\n", $dtend ;

        } elsif ( $line =~ /^END:VEVENT/ ) {

# it's only on closing an event definition that we have
# a complete local event identifier

                $local_event_id = "$summary" . ";" . "$dtstart" . ";" . "$dtend" ;


                if ( defined ( $events{"$local_event_id"} )) {

#                       duplicate event

                        printf STDOUT "\n\tduplicate\t%s\n", $local_event_id ;

#                       free event storage

                        @event = () ;
                        $in_event = 0 ;
                        $duplicate++ ;
                } else {

#                       new event
                        $events{$local_event_id} = 1;

                        if ($in_event) {

#                               print every lines of stored event

                                foreach $line (@event) {
                                        printf {$filedesc{$calendar}} "%s", $line ;
                                }
                                @event = () ;
                                $in_event = 0 ;
                                $num_event++ ;
                                $in_header = 1 ;

#                               show progress
                                if (($num_event % 100) == 0) {
                                        printf STDOUT "\n%8d", $num_event ;
                                } else {
                                        print STDOUT "." ;
                                }
                        }
                }
        } elsif ( $in_event == 0 ) {
                $in_header = 1 ;
        }

#       store every line of event or header

        if ($in_event || $in_header) {
                push (@event, $line) ;
        }

}

printf STDOUT "\nevents:%12d\n", $num_event ;
printf STDOUT "duplicates:%8d\n", $duplicate ;

#                       print every lines of ending

                        foreach $line (@event) {
                                printf {$filedesc{$calendar}} "%s", $line ;
                        }

close ($filedesc{$calendar}) ;
exit 0 ;
eof
$ chmod u+x duplicate.pl

และนี่คือวิธีที่ฉันใช้:

  1. จากCalendarส่งออกปฏิทินที่กำหนดผ่าน:

    File > Export > Export...

    สมมติว่ามันคือ: Documents/Calendar/2015/professionnal.ics

    หมายเหตุ: นี่จะเป็นการสำรองข้อมูลในกรณีที่เกิดปัญหาและมีประโยชน์มากกว่าการจัดการไฟล์ด้วยความช่วยเหลือของ Time Machine

  2. ติดตั้งสคริปต์ข้างต้นเป็น:

    ~/Documents/Calendar/src/duplicate.pl
    
  3. ไปที่ไดเรกทอรีเพื่อทดสอบรุ่นที่แน่นอนตัวอย่างเช่น:

    mkdir ~/Documents/Calendar/2015.fixed
    cd ~/Documents/Calendar/2015.fixed
    
  4. วิ่งduplicate.pl:

    ../src/duplicate.pl <../2015/professionnal.ics
    

    ซึ่งจะแสดงจำนวนของกิจกรรมที่อ่านและจำนวนของการทำซ้ำที่พบและสร้างที่นี่เป็นรุ่นที่คงที่ของปฏิทิน:

    ~/Documents/Calendar/2015.fixed/professionnal.ics
    
  5. เปรียบเทียบผลลัพธ์กับรุ่นเดิมที่เสียหายเพื่อตรวจสอบว่าทุกอย่างเรียบร้อยดี:

     diff ../2015/professionnal.ics .
    
  6. ภายในCalendarเลือกปฏิทินprofessionnalและลบผ่าน:

    Edit > Delete

  7. นำเข้าตัวแก้ไขผ่าน:

    File > Import > Import...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.