GNU/Linux >> Belajar Linux >  >> Linux

Memotong file saat sedang digunakan (Linux)

Pada coreutils 7.0, ada truncate perintah.


Hal yang menarik tentang file yang ditumbuhkan kembali adalah bahwa sekitar 128 KB pertama akan menjadi nol setelah Anda memotong file dengan menyalin /dev/null lebih dari itu. Hal ini terjadi karena file terpotong menjadi panjang nol, tetapi deskriptor file dalam aplikasi tetap mengarah tepat setelah penulisan terakhirnya. Saat menulis lagi, sistem file memperlakukan awal file sebagai nol byte - tanpa benar-benar menulis nol ke disk.

Idealnya, Anda harus meminta vendor aplikasi untuk membuka file log dengan O_APPEND bendera. Ini berarti setelah Anda memotong file, penulisan berikutnya akan secara implisit mencari ke akhir file (artinya kembali ke offset nol) dan kemudian menulis informasi baru.

Kode ini memasang output standar sehingga ada di O_APPEND mode dan kemudian memanggil perintah yang diberikan oleh argumennya (agak seperti nice menjalankan perintah setelah menyesuaikan level bagusnya, atau nohup menjalankan perintah setelah memperbaiki sesuatu sehingga mengabaikan SIGHUP).

#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>

static char *arg0 = "<unknown>";

static void error(const char *fmt, ...)
{
    va_list args;
    int errnum = errno;
    fprintf(stderr, "%s: ", arg0);
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    if (errnum != 0)
        fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
    putc('\n', stderr);
    fflush(0);
    exit(1);
}

int main(int argc, char **argv)
{
    int attr;
    arg0 = argv[0];

    if (argc < 2)
        error("Usage: %s cmd [arg ...]", arg0);
    if ((attr = fcntl(1, F_GETFL, &attr)) < 0)
        error("fcntl(F_GETFL) failed");
    attr |= O_APPEND;
    if (fcntl(1, F_SETFL, attr) != 0)
        error("fcntl(F_SETFL) failed");
    execvp(argv[1], &argv[1]);
    error("failed to exec %s", argv[1]);
    return(1);
}

Pengujian saya terhadapnya agak biasa saja, tetapi hampir tidak cukup untuk meyakinkan saya bahwa itu berhasil.

Alternatif yang lebih sederhana

Billy mencatat dalam jawabannya bahwa '>> ' adalah operator append - dan memang, pada Solaris 10, bash (versi 3.00.16(1)) menggunakan O_APPEND flag - sehingga membuat kode di atas tidak diperlukan, seperti yang ditunjukkan ('Black JL:' adalah prompt saya di mesin ini):

Black JL: truss -o bash.truss bash -c "echo Hi >> x3.29"
Black JL: grep open bash.truss
open("/var/ld/ld.config", O_RDONLY)             Err#2 ENOENT
open("/usr/lib/libcurses.so.1", O_RDONLY)       = 3
open("/usr/lib/libsocket.so.1", O_RDONLY)       = 3
open("/usr/lib/libnsl.so.1", O_RDONLY)          = 3
open("/usr/lib/libdl.so.1", O_RDONLY)           = 3
open("/usr/lib/libc.so.1", O_RDONLY)            = 3
open("/platform/SUNW,Ultra-4/lib/libc_psr.so.1", O_RDONLY) = 3
open64("/dev/tty", O_RDWR|O_NONBLOCK)           = 3
stat64("/usr/openssl/v0.9.8e/bin/bash", 0xFFBFF2A8) Err#2 ENOENT
open64("x3.29", O_WRONLY|O_APPEND|O_CREAT, 0666) = 3
Black JL:

Gunakan pengalihan tambahan daripada kode pembungkus ('cantrip') di atas. Ini hanya untuk menunjukkan bahwa ketika Anda menggunakan satu teknik tertentu untuk tujuan (valid) lainnya, mengadaptasinya ke teknik lain belum tentu merupakan mekanisme yang paling sederhana - meskipun berhasil.


Arahkan ulang output menggunakan>> alih-alih>. Ini akan memungkinkan Anda untuk memotong file tanpa file tumbuh kembali ke ukuran aslinya. Juga, jangan lupa untuk mengalihkan STDERR (2>&1).

Jadi hasil akhirnya adalah:myprogram >> myprogram.log 2>&1 &


Linux
  1. Dasar-dasar Izin File Linux

  2. Linux – Semuanya Adalah File?

  3. Apakah Menggunakan Rsync Saat Sumber Diperbarui Aman?

  1. Cara memindahkan file di Linux

  2. Memahami Izin File Linux

  3. Mengapa pilih digunakan di Linux

  1. Perintah Ekor Linux

  2. Perintah Sentuh Linux

  3. Perintah Cat di Linux