এতে ফাইলের পাইপ লিখনকে ব্যাহত না করে খালি করা


12

আমার একটি প্রোগ্রাম রয়েছে যার আউটপুট আমি লগ ফাইলে পুনঃনির্দেশ করি:

./my_app > log

আমি সময়ে সময়ে (চাহিদা অনুসারে) লগটি সাফ করতে চাই (যেমন খালি) এবং বিভিন্ন ধরণের জিনিস চেষ্টা করে দেখতে চাই

cat "" > log

তবে এটি সর্বদা মনে হয় যে আসল পাইপটি তখন ব্যাহত হয় এবং প্রোগ্রামটি আর আউটপুটটিকে লগ ফাইলে পুনর্নির্দেশ করে না।

এটি করার কোনও উপায় আছে?

হালনাগাদ

দ্রষ্টব্য যে আমি আউটপুট উত্পাদন অ্যাপ্লিকেশন পরিবর্তন করতে পারবেন না। এটি কেবল স্টডআউট করার জন্য এটি ছুঁড়ে ফেলেছে এবং আমি এটি একটি লগ এ সংরক্ষণ করতে চাই যাতে আমার যখন প্রয়োজন হয় তখন এটি পরিদর্শন করতে পারি এবং যখন আমি চাই তখন এটি সাফ করি। তবে আমার অ্যাপ্লিকেশনটি পুনরায় চালু করার দরকার নেই।


এজন্য আপনি সাধারণত জিনিসগুলি লগ করতে লগিং ডেমন ব্যবহার করেন ...
কিউই

@ কিউই আপনি কীভাবে সমস্যার সমাধান করবেন তা বিশদ দিয়ে বলতে পারেন?
বঙ্গব

ভাল আপনি সাধারণত একটি লগ ডেমন ব্যবহার করেন বা আপনার অ্যাপ্লিকেশনটিকে লগটি পরিচালনা করতে দেয় কারণ আউটপুটে জিনিস লিখতে এবং এটিকে পুনর্নির্দেশ করা নির্ভরযোগ্য নয়। আপনি কটাক্ষপাত করা উচিত syslogdবাlogrotate
Kiwy

2
আপনি যদি কাজগুলি ./my_app >> log(সংযোজন করার জন্য বাধ্য করা) এবং cp /dev/null logএটি কেটে ফেলার জন্য কাজ করেন তবে কি কাজ করা যায়?
মার্ক প্লটনিক

1
আপনি কোন ত্রুটি বার্তা পাবেন? কী আচরণ দেখছেন? "এর আউটপুটটি আর লগ ফাইলে পুনর্নির্দেশ করে না" খুব সুনির্দিষ্ট নয়। এছাড়াও, cat "" > logকোনও বৈধ catকমান্ড নয় যেহেতু কোনও ফাইল ডাকা হয়নি ""
মাইকেল

উত্তর:


13

এই সমস্যাটির আর একটি রূপ দীর্ঘকালীন চলমান অ্যাপ্লিকেশনগুলির সাথে ঘটে যার লগগুলি পর্যায়ক্রমে ঘোরানো হয়। এমনকি যদি আপনি আসল লগ (উদাহরণস্বরূপ mv log.txt log.1) সরিয়ে নিয়ে থাকেন এবং কোনও প্রকৃত লগিং হওয়ার আগে একই নামের একটি ফাইলের সাথে তাৎক্ষণিকভাবে এটি প্রতিস্থাপন করেন, প্রক্রিয়াটি যদি ফাইলটি উন্মুক্ত করে রাখে তবে তা হয় লেখালেখিতে শেষ হয়ে যাবে log.1(কারণ এটি এখনও হতে পারে খোলা ইনোড) বা কিছুই নেই।

এটির সাথে মোকাবিলার একটি সাধারণ উপায় হ'ল প্রক্রিয়াটিতে একটি সিগন্যাল হ্যান্ডলার প্রয়োগ করা যা এটির লগগুলি বন্ধ করে এবং পুনরায় খোলে। তারপরে, যখনই আপনি লগটি সরানো বা সাফ করতে চান (মুছে ফেলা), ততক্ষণে প্রক্রিয়াতে সেই সংকেতটি প্রেরণ করুন।

বাশের জন্য এখানে একটি সহজ বর্ননা - আমার ক্রুডি শেল দক্ষতা ক্ষমা করুন (তবে আপনি যদি সর্বোত্তম অনুশীলন ইত্যাদির জন্য এটি সম্পাদনা করতে যাচ্ছেন তবে দয়া করে নিশ্চিত করুন যে আপনি প্রথমে কার্যকারিতাটি বুঝতে পেরেছেন এবং সম্পাদনার আগে আপনার পুনর্বিবেচনা পরীক্ষা করেছেন ):

#!/bin/bash

trap sighandler INT

function sighandler () {
    touch log.txt
    exec &> log.txt
}

echo $BASHPID
exec &> log.txt

count=0;
while [ $count -lt 60 ]; do
    echo "$BASHPID Count is now $count"
    sleep 2
    ((count++))
done          

ব্যাকগ্রাউন্ডে কাঁটাচামচ করে এটি শুরু করুন:

> ./test.sh &
12356

লক্ষ্য করুন এটি তার পিআইডি টার্মিনালে রিপোর্ট করে এবং তারপরে লগইন শুরু হয় log.txt। আপনার এখন চারপাশে খেলার জন্য 2 মিনিট সময় রয়েছে। কয়েক সেকেন্ড অপেক্ষা করুন এবং চেষ্টা করুন:

> mv log.txt log.1 && kill -s 2 12356

কেবল প্লেইন kill -2 12356আপনার এখানে কাজ করতে পারে। সিগন্যাল 2 হ'ল সিগিন্ট (এটি সিটিআরএল-সি যা করে তাও তাই আপনি পূর্বের অংশে এটি চেষ্টা করে দেখতে পারেন এবং অন্য টার্মিনাল থেকে লগফিলটি সরাতে বা মুছে ফেলতে পারেন), যা trapফাঁসানো উচিত। পরীক্ষা করা;

> cat log.1
12356 Count is now 0
12356 Count is now 1
12356 Count is now 2
12356 Count is now 3
12356 Count is now 4
12356 Count is now 5
12356 Count is now 6
12356 Count is now 7
12356 Count is now 8
12356 Count is now 9
12356 Count is now 10
12356 Count is now 11
12356 Count is now 12
12356 Count is now 13
12356 Count is now 14

এখন দেখা যাক আমরা এটি সরিয়ে নেওয়া সত্ত্বেও এটি এখনও কোনও লেখা রয়েছে log.txtকিনা:

> cat log.txt
12356 Count is now 15
12356 Count is now 16
12356 Count is now 17
12356 Count is now 18
12356 Count is now 19
12356 Count is now 20
12356 Count is now 21

লক্ষ্য করুন যেখানে এটি ছেড়ে গেছে ঠিক সেখানে চলছে। আপনি যদি রেকর্ড রাখতে না চান তবে এটি মুছে ফেলার মাধ্যমে লগটি সাফ করুন

> rm -f log.txt && kill -s 2 12356

পরীক্ষা করে দেখুন:

> cat log.txt
12356 Count is now 29
12356 Count is now 30
12356 Count is now 31
12356 Count is now 32
12356 Count is now 33
12356 Count is now 34
12356 Count is now 35
12356 Count is now 36

এখনো চলছে.

আপনি মৃত্যুদণ্ডপ্রাপ্ত সাবপ্রসেসের জন্য শেল স্ক্রিপ্টে এটি করতে পারবেন না, দুর্ভাগ্যক্রমে, কারণ যদি এটি অগ্রভাগে থাকে তবে ব্যাশের নিজস্ব সিগন্যাল হ্যান্ডলারগুলি trapস্থগিত করা হয়, এবং আপনি যদি এটি পটভূমিতে কাঁটাচামচ করেন তবে আপনি এটি পুনরায় সাইন করতে পারবেন না আউটপুট। অর্থাৎ এটি আপনার প্রয়োগে প্রয়োগ করতে হবে in

যাহোক...

আপনি যদি অ্যাপ্লিকেশনটি সংশোধন করতে না পারেন (উদাহরণস্বরূপ, আপনি এটি লেখেন নি), আমার কাছে একটি সি এল এল ইউটিলিটি রয়েছে যা আপনি মধ্যস্থতাকারী হিসাবে ব্যবহার করতে পারেন। আপনি এটির একটি সাধারণ সংস্করণ কোনও স্ক্রিপ্টেও প্রয়োগ করতে পারেন যা লগের পাইপ হিসাবে কাজ করে:

#!/bin/bash

trap sighandler INT

function sighandler () {
    touch log.txt
    exec 1> log.txt
}

echo "$0 $BASHPID"
exec 1> log.txt

count=0;
while read; do
    echo $REPLY
done  

এটি কল করুন pipetrap.sh। আপনি যে অ্যাপ্লিকেশনটি লগ করতে চান তা অনুকরণ করে পরীক্ষা করার জন্য এখন আমাদের একটি পৃথক প্রোগ্রাম প্রয়োজন:

#!/bin/bash

count=0
while [ $count -lt 60 ]; do
    echo "$BASHPID Count is now $count"
    sleep 2
    ((count++))
done           

তা হবে test.sh:

> (./test.sh | ./pipetrap.sh) &
./pipetrap.sh 15859

এগুলি পৃথক পিআইডি সহ দুটি পৃথক প্রক্রিয়া। test.shএর আউটপুট সাফ করার জন্য , যা দিয়ে ফানেল করা হচ্ছে pipetrap.sh:

> rm -f log.txt && kill -s 2 15859

পরীক্ষা করে দেখুন:

>cat log.txt
15858 Count is now 6
15858 Count is now 7
15858 Count is now 8

15858, test.shএখনও চলছে এবং এর আউটপুট লগ হচ্ছে। এই ক্ষেত্রে, অ্যাপ্লিকেশনটিতে কোনও পরিবর্তন করার প্রয়োজন নেই।


সুন্দর ব্যাখ্যার জন্য ধন্যবাদ। তবে আমার ক্ষেত্রে আমি আপনার সমাধানটি প্রয়োগের জন্য অ্যাপ্লিকেশনটি পরিবর্তন করতে পারি না।
বঙ্গব

2
আপনি যদি নিজের অ্যাপ্লিকেশনটিতে একটি সিগন্যাল হ্যান্ডলার বাস্তবায়ন করতে না পারেন (কারণ আপনি এটির সময়কালটি সংশোধন করতে পারবেন না), আপনি এই কৌশলটি একটি সিগন্যাল ট্র্যাপের মাধ্যমে লগটি পাইপ করতে ব্যবহার করতে পারেন - "তবে ..." এর
স্টাফটি দেখুন

ঠিক আছে আমি চেষ্টা করে দেখাব যে এটি কীভাবে চলেছে।
বঙ্গভবন

অবশেষে এর জন্য সি তে একটি সি এল আই অ্যাপ্লিকেশন লেখা আছে (দুঃখিত এটি মূলত উদ্দিষ্টের চেয়ে কিছুটা বেশি সময় নিয়েছে): cognitivedissonance.ca/cogware/pipelog
স্বর্ণলোকস

6

টি এল; ডিআর

অ্যাপড মোডে আপনার লগ ফাইলটি খুলুন :

cmd >> log

তারপরে, আপনি এটির সাথে নিরাপদে এটি কেটে ফেলতে পারেন:

: > log

বিস্তারিত

বোর্ন-এর মতো শেল দিয়ে, ফাইলটি লেখার জন্য খোলা যেতে পারে এমন 3 টি প্রধান উপায় রয়েছে। কেবল লেখার ক্ষেত্রে ( >), পড়ুন + লিখুন ( <>) অথবা অ্যাপড (এবং কেবলমাত্র লেখার জন্য >>) মোড।

প্রথম দুই, কার্নেল বর্তমান অবস্থান আপনি মনে (আপনার, আমি বলতে চাচ্ছি, খোলা ফাইল বিবরণ , সমস্ত ফাইল বর্ণনাকারী যে সদৃশ অথবা এক আপনার উপর ফাইল খোলা থেকে forking দ্বারা এটি উত্তরাধিকারসূত্রে করেছে ভাগ করে নেওয়া) আছে সেগুলিও ফাইল।

যখন তুমি কর:

cmd > log

logস্ট্যান্ডআউটের জন্য শেল দ্বারা কেবল লেখার মোডে খোলা আছে cmd

cmd(এটির প্রাথমিক প্রক্রিয়াটি শেল এবং সমস্ত সম্ভাব্য বাচ্চাদের দ্বারা উদ্ভূত হয়েছিল) তাদের স্টাডআউটে লেখার সময়, কার্সার অবস্থানে লিখুন যে ফাইলটি তারা যে ফাইলটিতে ভাগ করে থাকে তার উন্মুক্ত ফাইলের বিবরণ দিয়ে থাকে।

উদাহরণস্বরূপ, যদি cmdপ্রাথমিকভাবে লেখেন zzzতবে পজিশনটি ফাইলে 4 টি অফসেটে থাকবে এবং পরের বার cmdবা তার শিশুরা ফাইলে লিখবে, সেখানে ফাইলটি বড় হওয়া বা ব্যবধানে সঙ্কুচিত কিনা তা নির্বিশেষে ডেটা লেখা হবে ।

যদি ফাইলটি সঙ্কুচিত হয়ে থাকে, উদাহরণস্বরূপ যদি এটি একটি দিয়ে কাটা হয়েছে

: > log

এবং cmdলিখেছেন xx, সেগুলি xxঅফসেটে লেখা হবে 4এবং প্রথম 3 টি অক্ষর NUL অক্ষর দ্বারা প্রতিস্থাপিত হবে।

$ exec 3> log # open file on fd 3.
$ printf zzz >&3
$ od -c log
0000000   z   z   z
0000003
$ printf aaaa >> log # other open file description -> different cursor
$ od -c log
0000000   z   z   z   a   a   a   a
0000007
$ printf bb >&3 # still write at the original position
$ od -c log
0000000   z   z   z   b   b   a   a
0000007
$ : > log
$ wc log
0 0 0 log
$ printf x >&3
$ od -c log
0000000  \0  \0  \0  \0  \0   x
0000006

এর অর্থ আপনি কেবলমাত্র রাইটিং-মোডে খোলা একটি ফাইলকে ছাঁটাই করতে পারবেন না (এবং এটি পড়ার + লেখার জন্য একই ) যেমনটি আপনি করেন, ফসলে ফাইল বর্ণনাকারী ফাইল খোলা প্রসেসগুলি NUL অক্ষর ছেড়ে দেবে ফাইল (ওএস / এক্স ব্যতীত এগুলি সাধারণত ডিস্কে স্থান নেয় না, যদিও তারা স্পার্স ফাইল হয়ে যায়)।

পরিবর্তে (এবং আপনি বেশিরভাগ অ্যাপ্লিকেশনগুলি লক্ষ্য করবেন যে তারা যখন লগ ফাইল লিখবেন ) তখন আপনার ফাইলটি অ্যাপেন্ড মোডে খোলা উচিত :

cmd >> log

অথবা

: > log && cmd >> log

যদি আপনি একটি খালি ফাইল শুরু করতে চান।

অ্যাপেন্ড মোডে, সমস্ত লেখাগুলি ফাইলের শেষে তৈরি করা হয়েছিল, শেষ লেখার স্থানটি যেখানেই ছিল তা নির্বিশেষে:

$ exec 4>> log
$ printf aa >&4
$ printf x >> log
$ printf bb >&4
$ od -c log
0000000   a   a   x   b   b
0000005
$ : > log
$ printf cc >&4
$ od -c log
0000000   c   c
0000002

এটি আরও নিরাপদ যেমন দুটি প্রক্রিয়া ভুল করে ফাইলটি (সেইভাবে) ফাইলটি খোলে (উদাহরণস্বরূপ যদি আপনি একই ডেমনের দুটি উদাহরণ শুরু করেছেন), তাদের আউটপুট একে অপরকে ওভাররাইট করবে না।

লিনাক্সের সাম্প্রতিক সংস্করণগুলিতে আপনি বর্তমান অবস্থান এবং ফাইল ফাইল বিবরণকারী অ্যাপেন্ড মোডে খোলা আছে কিনা তা যাচাই করে দেখতে পারেন /proc/<pid>/fdinfo/<fd>:

$ cat /proc/self/fdinfo/4
pos:        2
flags:      0102001

বা সাথে:

$ lsof +f G -p "$$" -ad 4
COMMAND  PID USER   FD   TYPE  FILE-FLAG DEVICE SIZE/OFF     NODE NAME
zsh     4870 root    4w   REG 0x8401;0x0 252,18        2 59431479 /home/chazelas/log
~# lsof +f g -p "$$" -ad 4
COMMAND  PID USER   FD   TYPE FILE-FLAG DEVICE SIZE/OFF     NODE NAME
zsh     4870 root    4w   REG   W,AP,LG 252,18        2 59431479 /home/chazelas/log

এই পতাকাগুলি ..._ ফ্ল্যাগগুলির সাথে openসিস্টেম কলে পাস করেছে ।

$ gcc -E - <<< $'#include <fcntl.h>\nO_APPEND O_WRONLY' | tail -n1
02000 01

( O_APPEND0x400 বা অষ্টাল 02000)

শেল তাই >>সাহায্যে ফাইল খোলে O_WRONLY|O_APPEND(এবং 0100000 এখানে O_LARGEFILE যা এই প্রশ্নের প্রাসঙ্গিক নয় হয়) যখন >হয় O_WRONLYশুধুমাত্র (এবং <>হল O_RDWRশুধুমাত্র)।

আপনি যদি এটি করেন:

sudo lsof -nP +f g | grep ,AP

এতে খোলা ফাইলগুলির সন্ধান O_APPENDকরতে, আপনি বর্তমানে আপনার সিস্টেমে লেখার জন্য বেশিরভাগ লগ ফাইলগুলি খোলা পাবেন।


আপনি কেন :(কোলন) ব্যবহার করবেন : > ?
মুভেরিসেক

1
@Mvorisek, যে কমান্ডের আউটপুট কোনো আউটপুট উত্পাদন করে পুনর্নির্দেশ করতে দেওয়া হল: :। একটি আদেশ ছাড়া, ব্যবহার শাঁসের মধ্যে পরিবর্তিত হয়।
স্টাফেন চেজেলাস

1

আমি যদি সঠিকভাবে বুঝতে পারি তবে teeমনে হয় এটি একটি যুক্তিসঙ্গত পদ্ধতির মতো:

$ ./myapp-that-echoes-the-date-every-second | tee log > /dev/null &
[1] 20519
$ head log
Thu Apr  3 11:29:34 EDT 2014
Thu Apr  3 11:29:35 EDT 2014
Thu Apr  3 11:29:36 EDT 2014
$ > log
$ head log
Thu Apr  3 11:29:40 EDT 2014
Thu Apr  3 11:29:41 EDT 2014
Thu Apr  3 11:29:42 EDT 2014

1

দ্রুত সমাধান হিসাবে আপনি ঘূর্ণন সহ একটি লগ ব্যবহার করতে পারেন (উদাহরণস্বরূপ দৈনিক রোটেশন):

date=`date +%Y%m%d`
LOGFILE=/home/log$date.log

এবং এটিতে লগিং পুনর্নির্দেশ ./my_app >> log$date.log


আমি চাহিদা অনুযায়ী ঘুরতে সক্ষম হতে চাই। এটি আসলে একটি লগ যা একটি স্বয়ংক্রিয় পরীক্ষার সময় উত্পাদিত হয় এবং আমি পরীক্ষাটি চালানোর আগে এটি পরিষ্কার করতে চাই।
বঙ্গব

0

এটি এমন একটি সমস্যা যা দীর্ঘদিন ধরে সিসলগ দিয়ে সমাধান করা হয়েছে (এটির সমস্ত রূপগুলিতে) তবে দুটি সরঞ্জাম রয়েছে যা আপনার বিশেষ সমস্যাটিকে ন্যূনতম চেষ্টা করে সমাধান করবে।

প্রথম, আরও বহনযোগ্য তবে কম বহুমুখী সমাধান হ'ল লগার (কোনও প্রশাসকের সরঞ্জামবক্সের জন্য এটি অবশ্যই থাকা উচিত)। এটি একটি সহজ ইউটিলিটি যা সিসলগে স্ট্যান্ডার্ড ইনপুটটি অনুলিপি করে। (বাক্সটি পাস করা, এবং ফাইল রোটেশন লোগ্রোটেট এবং সিসলগের সমস্যা তৈরি করা)

দ্বিতীয়টি, আরও মার্জিত তবে কম পোর্টেবল সমাধান হ'ল সিসলগ-এনজি যা স্ট্যান্ডার্ড সিসলোগ সকেট থেকে লগ বার্তা গ্রহণ করা ছাড়াও প্রোগ্রামগুলি কার্যকর করতে পারে যা লগারের মাধ্যমে আউটপুট ফিল্টার করা হয়। (আমি এখনও এই বৈশিষ্ট্যটি ব্যবহার করি নি, তবে আপনি যা করতে চাইছেন তা এটি পুরোপুরি দেখাচ্ছে))

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.