Here's some sample log file output:
Feb 26 23:04:55 pegasus internal-sftp[32524]: session opened for local user joeuser from [123.123.123.123]
Feb 26 23:04:57 pegasus internal-sftp[32524]: opendir "/home/joeuser"
Feb 26 23:04:58 pegasus internal-sftp[32524]: closedir "/home/joeuser"
Feb 26 23:05:01 pegasus internal-sftp[32524]: opendir "/home/joeuser/"
Feb 26 23:05:01 pegasus internal-sftp[32524]: closedir "/home/joeuser/"
Feb 26 23:05:02 pegasus internal-sftp[32524]: opendir "/home/joeuser/upload"
Feb 26 23:05:02 pegasus internal-sftp[32524]: closedir "/home/joeuser/upload"
Feb 26 23:05:07 pegasus internal-sftp[32524]: opendir "/home/joeuser/upload"
Feb 26 23:05:07 pegasus internal-sftp[32524]: closedir "/home/joeuser/upload"
Feb 26 23:05:09 pegasus internal-sftp[32524]: session closed for local user joeuser from [123.123.123.123]
Which user is which?
If you take notice of the output above there is a number between square brackets , internal-sftp[32524]
. The number is 32524. This represents the session ID for user joeuser, so you can use this string together which messages relate to which user's login.
Rotating the logs
You can modify the log rotation schedule for various logs under /etc/logrotate.d/*
. Each log file typically has a corresponding file in this directory. So you could change the syslog
file there, for example or create your own for your sftp.log
logfile.
Also logrotate
has a configuration file, /etc/logrotate.conf
which contains these lines:
# rotate log files weekly
weekly
# keep 4 weeks worth of backlogs
rotate 4
These are what the files in the /etc/logrotate.d
directory use, if they don't have a setting of their own. So most files are rotated weekly and 4 of them are kept. If you wanted to keep 6 months it would be 4*6 = 24 for the rotate
option to keep 6 months, roughly.
Example
Given you're logging to /var/log/sftp.log
via syslog
you'll need to make your changes in this file, /etc/logrotate.d/syslog
. Your file will look like this after making the required changes:
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
/var/log/sftp.log
{
rotate 24
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}
Since you're using syslog
you'll have to rotate all these log files as well, keep 24 weeks worth of these as well. If this is unacceptable then your only other course of action would be to create a separate section in this file, syslog
like so:
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}
/var/log/sftp.log
{
rotate 24
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}
This has some side-effects, one being that you'll be restarting the syslog
daemon 2 times each week instead of once. But the logroate syntax does not allow for fine granular control of the rotation schedule for certain logfiles while not rotating others, when the log files are being generated by the same service, i.e. syslog
.
References
It is possible like this, but as others have said, the safest option is the generation of a new file and then a move of that file to overwrite the original.
The below method loads the lines into BASH, so depending on the number of lines from tail
, that's going to affect the memory usage of the local shell to store the content of the log lines.
The below also removes empty lines should they exist at the end of the log file (due to the behaviour of BASH evaluating "$(tail -1000 test.log)"
) so does not give a truly 100% accurate truncation in all scenarios, but depending on your situation, may be sufficient.
$ wc -l myscript.log
475494 myscript.log
$ echo "$(tail -1000 myscript.log)" > myscript.log
$ wc -l myscript.log
1000 myscript.log
Best Answer
The problem is that your shell is setting up the command pipeline before running the commands. It's not a matter of "input and output", it's that the file's content is already gone before tail even runs. It goes something like:
>
output file for writing, truncating ittail
.tail
runs, opens/home/pi/Documents/test
and finds nothing thereThere are various solutions, but the key is to understand the problem, what's actually going wrong and why.
This will produce what you are looking for,
Explanation :
$()
is called command substitution which executestail -n 50 /home/pi/Documents/test
> /home/pi/Documents/test
redirects output ofecho "$(tail -n 50 /home/pi/Documents/test)"
to the same file.