Log-rotate delete original file after compressing - linux

I have following files in my someDir:
blacklistadm.out00009 blacklistadm.out00008 blacklistadm.out00007 blacklistadm.out00010 blacklistadm.out00025
I have following log rotation pattern in /etc/logrotate.d/:
someDir/blacklistadm.out*[0-9]{
weekly
missingok
compress
sharedscripts
postrotate
rm -f someDir/blacklistadm.out*[0-9]
endscript
}
When the log rotation script is run, it is somehow deleting all the files in someDir. What I want is to .gz all the files and after compressing delete the original file. I don't want to delete the .gz files.

The files are being deleted because your globbing is being used incorrectly.
blacklistadm.out*[0-9]
literally expands to any file starting with "blacklistadm.out" followed by any sequence of 0 or more characters, ending with a single character within the defined range of 0-9.
This is globbing on to everything obviously, because all your files start with "blacklistadm.out" and end in a number, so when you run your postrotate script with an identical glob you are matching everything in that directory and deleting it.

Related

How to copy multiple files with varying version numbers from one directory to another using bash?

I have a folder /home/user/Document/filepath where I have three files namely file1-1.1.0.txt, file2-1.1.1.txt, file3-1.1.2.txt
and another folder named /home/user/Document/backuppath where I have to move files from /home/user/Document/folderpath which has file1-1.0.0.txt, file2-1.0.1.txt and file3-1.0.2.txt
task is to copy the specific files from folder path to backup path.
To summarize:
the below is the files.txt where I listed the files which has to be copied:
file1-*.txt
file2-*.txt
The below is the move.sh script that execute the movements
for file in `cat files.txt`; do cp "/home/user/Document/folderpath/$file" "/home/user/Documents/backuppath/" ; done
for the above script I am getting the error like
cp: cannot stat '/home/user/Document/folderpath/file1-*.txt': No such file or directory found
cp: cannot stat '/home/user/Document/folderpath/file2-*.txt': No such file or directory found
what I would like to accomplish is that I would like to use the script to copy specific files using * in the place of version numbers., since the version number may vary in the future.
You have wildcard characters in your files.txt. In your cp command, you are using quotes. These quotes prevent the wildcards to be expanded, as you can clearly see from the error message.
One obvious possibility is to not use quotes:
cp /home/user/Document/folderpath/$file /home/user/Documents/backuppath/
Or not use a loop at all:
cp $(<files.txt) /home/user/Documents/backuppath/
However, this would of course break if one line in your files.txt is a filename pattern which contains white spaces. Therefore, I would recommend a second loop over the expanded pattern:
while read file # Puts the next line into 'file'
do
for f in $file # This expands the pattern in 'file'
do
cp "/home/user/Document/folderpath/$f" /home/user/Documents/backuppath
done
done < files.txt

How to rename/move a file and retain the middle of the filename? I'm using wildcards to find file

I'm trying to rename the file process_12345678.pdf to process_12345678_0219.pdf.
I'm adding the month/year before the file extension, and this is what I've been trying.
mv process_*{,_$(date +%m%y)}.pdf
This changes the file name to process_*_0219.pdf
The number in the middle, 12345678, changes every time the process is run. I can't remember or find how to retain the process number.
for file in process_*.pdf
do
mv "$file" "${file%.pdf}_$(date +%m%y).pdf"
done
see https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html

How to exclude ".gz" files in logrotate

I am using logrotate version 3.12.3. How do I tell logrotate to exclude files that are already rotated/compressed?
For example, if I am rotating all files in /var/log as
"/var/log/*" {
compress
missingok
dateext
rotate 4
size=5000k
}
after a file is compressed, how do I tell logrotate to not rotate already rotated/compressed files? For example:
/var/log/file1
after logrotation it becomes
/var/log/file1.20211212.gz
I tried
tabooext + .gz
on top of definitions but it doesn't seem to take effect.
From man logrotate
include file_or_directory
Reads the file given as an argument as if it was included inline where the include directive appears. If a directory is given,
most of the files in that
directory are read in alphabetic order before processing of the including file continues. The only files which are ignored are
files which are not regular
files (such as directories and named pipes) and files whose names end with one of the taboo extensions, as specified by the
tabooext directive.
If something like below worked, that would have been good.
/var/log/*[!".gz"] {
}
Thank you.
EDIT
Maybe do something like
/var/log/*[!.][!g][!z] {
..
}
but it skips file named /var/log/test1gz. How do I match the . character with globbing?
Try to find all glob possibilities that does not accept *.gz. As you have three letters (., g, z), there are 2^3 = 8 possible combinations (3 characters, 2 states x and !x), minus one which is *.gz.
The seven other possibilities are the following:
All files that don't have an extension point as third last but end with gz (e.g. filegz)
/var/log/*[!.]gz
All files which 2-letters extension doesn't begin by g but ends by z (e.g. file.7z)
/var/log/*.[!g]z
All files which 2-letters extension begins by g but doesn't end by z (e.g. file.gg)
/var/log/*.g[!z]
All files that don't end with .gz but end with a z (e.g. file.ezz)
/var/log/*[!.][!g]z
All files that don't end with .gz but with g as second to last letter (e.g. file.cgi)
/var/log/*[!.]g[!z]
All files which 2-letters extension is not gz (e.g. file.hh)
/var/log/*.[!g][!z]
Finally, all files that don't finish by .gz (e.g. file.txt)
/var/log/*[!.][!g][!z]
So this gives us:
/var/log/*[!.]gz
/var/log/*.[!g]z
/var/log/*.g[!z]
/var/log/*[!.][!g]z
/var/log/*[!.]g[!z]
/var/log/*.[!g][!z]
/var/log/*[!.][!g][!z]
{
...
The combinations can be generated with python:
import itertools as it
suffix = '.gz'
states = ([x, '![%c]' % x] for x in suffix)
for res in it.product(*states):
print ''.join(res)
Hope it helps!
You don't need to specify a complete folder. You can define a file aswell. So first you should make sub folders for every service that you have a better overview. There you can place your logs into. You shouldn't put that on your complete log folder because there are some more rotate scripts located.
for example:
/var/log/yum.log {
missingok
notifempty
size 30k
yearly
create 0600 root root
}

How to specify the tar final structure

I have this structure:
release/folder1/file1
release/folder2/file2
...
release/folderN/fileN
I want to include all those folders (folder1, folder2 ... folderN) in a tar file.
The key is that I want these folders to be in the final tar within another directory named MYAPP so when you open the tar you can see this:
MYAPP/folder1/file1
MYAPP/folder2/file2
...
MYAPP/folderN/fileN
How can I achieve this without renaming the original "release" directory and/or creating new directories.
Is this possible to achive just in the tar process?
Thanks
Add
--transform=s#^release/#MYAPP/#
to your tar command line.
The argument of the --transform command line is a command that is passed to sed together with the file path before it is stored in the archive (use tar -tf to show the names of the files stored in the archive).
The command s#^release/#MYAPP/# tells sed to search (s) release/ at the beginning of the string (^) and replace it with MYAPP/.
The / at the end of the search and replace strings is needed to be sure the complete name of the component is release (to not replace release.txt). The # character is just a regex delimiter. Usually / is used as a regex delimiter but we prefer to use a different delimiter here to avoid the need to escape / (because it is used in the search and replace strings).
Read more in the documentation of tar and sed.

Execute program on Files in subDirectory

I have following architecture of files in a directory.
Directory
/A/abc.xyz
/B/abc.xyz
/C/abc.xyz
/D/abc.xyz
/E/abc.xyz
I want to execute a program on acb.xyz in each SubDirectory. Save Output files in different directory i.e. Directory/processed with the name of SubDirectory appended in the name of output files.
Can it be written in following way? Need corrections.
for i in `ls "Directory/"`
do
program.pl $i/abc.xyz > processed/$i-abc.xyz
done
for dir in Directory/*; do
program.pl "$dir/abc.xyz" > "processed/${dir##*/}-abc.xyz"
done
The ${dir##*/} part strips the leading directory names from $dir, so Directory/A becomes just A. I added quotes to ensure directory names with whitespace don't cause issue (a good habit, even if you know there are no spaces).
As an alternative to the string munging you could simplify this if you first change directory:
cd Directory
for dir in *; do
program.pl "$dir/abc.xyz" > "processed/$dir-abc.xyz"
done

Resources