cat / dev / null> file.log ไม่ตัดทอนไฟล์ขนาดใหญ่ในดาร์วิน


15

ในอดีตที่ผ่านมาบนระบบลินุกซ์, ฉันได้รับสามารถที่จะตัดขนาดใหญ่ล็อกไฟล์เปิด (นั่นคือแฟ้มที่จะถูกเขียนอย่างแข็งขันโดยกระบวนการที่) cat /dev/null > file.logโดยใช้

อย่างไรก็ตามใน 10.9 (Mavericks) ดูเหมือนจะไม่เป็นเช่นนั้น ฉันมีไฟล์ 11GB ที่กำลังเข้าสู่ระบบโดยแอปพลิเคชัน แต่เมื่อฉันทำคำสั่งเดียวกันกับไฟล์ดังกล่าวดูเหมือนว่าไม่มีอะไรเกิดขึ้น

เมื่อฉันลองทำสิ่งนี้ในไฟล์ขนาดเล็กมันก็ใช้ได้

นี่คือls -l /dev/null:

crw-rw-rw- 1 root wheel 3, 2 Dec 16 12:49 /dev/null

ฉันยังพยายามcp /dev/null file.logไม่ทำประโยชน์

คิดว่าฉันอาจใช้ประโยชน์จากฟังก์ชั่นการตัดทอน ( man 2 truncateในดาร์วิน) ฉันรวบรวมและวิ่งกับไฟล์สองไฟล์หนึ่งในขนาดที่ไม่สำคัญและอีกไฟล์บันทึกจริง อีกครั้งมันทำงานกับไฟล์เล็ก ๆ น้อย ๆ และไม่ทำงานในบันทึกที่มีขนาดใหญ่กว่ามาก

/*
 * Copyright (c) 2013 Thomas de Grivel <thomas@lowh.net>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 ...
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <unistd.h>

int main (int argc, const char **argv)
{
        int e = 0;
        while (--argc) {
                argv++;
                if (truncate(*argv, 0)) {
                        e = 4;
                        warn("%s", *argv);
                }
        }
        return e;
}

กระบวนการส่งคืน0โดยไม่คำนึงถึงไฟล์ที่ฉันใช้


คุณรู้ได้อย่างไรว่ามันไม่ทำงาน อะไรduหรือdu -hพูดอะไร เป็นไปได้หรือไม่ที่ไฟล์เป็นไฟล์แบบกระจาย
มิเคล

2
นอกจากนี้จุดประสงค์ในการรวมใบอนุญาตในโพสต์นี้คืออะไร ดูเหมือนว่าจะเป็นการเพิ่มสัญญาณรบกวนเท่านั้น
มิเคล

du -h /tmp/file.logผลลัพธ์ใน11G /tmp/file.log
chb

@Mikel ฉันรวมใบอนุญาตเป็นมารยาท ... คุณจะทราบว่าฉัน redacted ส่วนใหญ่
chb

1
ใบอนุญาตคือสิ่งที่ทำให้ไขว้เขว, อัญมณีที่แท้จริงที่นี่คือคำตอบ
iruvar

คำตอบ:


12

cat /dev/nullเป็นวิธีที่ซับซ้อนเล็กน้อยในการเขียนคำสั่งที่ไม่สร้างเอาต์พุต :หรือtrueเป็นคนที่ชัดเจนมากขึ้น

ในทุกcat /dev/null > file, : > fileและแม้กระทั่ง> fileในเปลือกหอยส่วนใหญ่เปลือกเปิดไฟล์ที่มี O_TRUNC บน stdout แล้วรันโปรแกรมที่ไม่ได้อะไรออกแล้วไฟล์จะถูกปิดและซ้ายถูกตัดทอน

อย่างไรก็ตามในกรณีนั้นหรือเมื่อใช้การtruncateเรียกของระบบหากกระบวนการที่เติมไฟล์นั้นไม่ได้เปิดด้วยแฟล็ก O_APPEND ในครั้งต่อไปที่มันเขียนไปยังไฟล์ descriptor ที่เปิดในไฟล์มันจะเขียน ข้อมูลที่ออฟเซ็ตมันอยู่ในไฟล์

เนื่องจาก HFS + ไม่รองรับไฟล์ที่กระจัดกระจายนั่นหมายความว่าพื้นที่ก่อนออฟเซตนั้นจะต้องถูกจัดสรรใหม่และเติมเต็มด้วยศูนย์โดยระบบ

ดังนั้นคุณต้องฆ่าแอปพลิเคชันที่กำลังเขียนไปยังไฟล์นั้นก่อนที่จะตัดทอนมัน หรือคุณต้องแน่ใจว่าแอปพลิเคชันเปิดไฟล์ด้วยO_APPEND(เช่น>>ถ้าใช้การเปลี่ยนเส้นทางของเชลล์)

หากคุณต้องการทดลองใช้งาน:

$ exec 3> x
$ yes | head -n 50000 >&3
$ ls -ls x
200 -rw-r--r--  1 me me  100000 Dec 16 21:32 x

ตอนนี้ fd 3 ของ shell ของฉันคือ 100000 bytes ภายในไฟล์

$ : > x
$ ls -ls x
0 -rw-r--r--  1 me me  0 Dec 16 21:34 x

ตอนนี้ไฟล์ถูกตัดทอน (ขนาด 0, ไม่มีพื้นที่ว่างบนดิสก์)

$ echo >&3
$ ls -ls x
200 -rw-r--r--  1 me me  100001 Dec 16 21:34 x

การเขียน 1 ไบต์ไปยังไฟล์ที่ออฟเซ็ต 100000 ตอนนี้ไฟล์มีขนาดใหญ่กว่า 100001 ไบต์ส่วนแรกทั้งหมดเป็นศูนย์จะใช้มากกว่า 100k บน HFS + แต่ประมาณหนึ่งบล็อกดิสก์ในระบบไฟล์ Unix อื่น ๆ ส่วนใหญ่

ในทางกลับกันด้วย:

$ exec 3>> x
$ yes | head -n 50000 >&3
$ ls -ls x
200 -rw-r--r--  1 me me  100000 Dec 16 21:35 x
$ : > x
$ echo >&3
$ ls -ls x
8 -rw-r--r--  1 me me  1 Dec 16 21:36 x

เขียน 1 ไบต์ไปยังแฟ้มไม่ได้อยู่ที่การชดเชย 100000 O_APPENDแต่ในตอนท้ายของไฟล์เพราะของ ไฟล์มีขนาดใหญ่ 1 ไบต์และใช้พื้นที่ในการถือหนึ่งไบต์


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