how do I retrieve 34 from "#34 PREEMPT Mon Mar 25 14:24:26 SGT 2013" - linux

I am new on Linux, how do I retrieve "34" from uname -v command?
My uname -v command result is #34 PREEMPT Mon Mar 25 14:24:26 SGT 2013
I wanna the number 34 only.

How about:
[cnicutar#ariel ~]$ echo '#34 PREEMPT ...' | sed 's/^#\([0-9]\+\).*/\1/'
34
You can also make that easier with -r:
sed -r 's/^#([0-9]+).*/\1/'

Using grep to show only the matching part of a line (-o) matching a # followed by one or more (+) digits ([0-9]):
uname -v | grep -o '#[0-9]\+'

Related

Bash script automation checking if certain version of app is installed or not [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I'm trying to automate some basics in my Linux Server, I would like to check if the certain version of application like git, python or some other apps are installed or not, if installed than update to latest stable version. Here is my script and it seems I'm missing something:
#!/bin/sh
CURRENT_OS=$(hostnamectl | awk '/Operating/ { print $3 }')
CURRENT_PY=$(python3 -V | awk '{ print $2 }')
CURRENT_GT=$(git --version | awk '{ print $3 }')
if [ $CURRENT_OS=~"Fedora" || $CURRENT_OS=~"Centos" || $CURRENT_OS=~"Red Hat" ]; then
echo "➥➥➥ Current System Is Based On $CURRENT_OS"
sudo dnf clean all
sudo dnf -y upgrade
if [ $CURRENT_PY!="Python 3.8" ]; then
echo "➥➥➥ Installing Latest Python Release"
sudo dnf -y install python3.8
else
echo "➥➥➥ Latest Python Release Found In System"
fi
fi
Also is there any chance to swap output of command python3 -V | awk '{ print $2 }' to 3.8 instead of 3.8.5?
And also how can I refactor the OS release check so either is Red Hat, Centos or Fedora?
You can filter the the Python version using sed, e.g.
python3 -V | awk '{ print $2 }' | sed 's/\([0-9]*\.[0-9]*\).*/\1/'
The question about the OS release check is not clear. If you only want to have the correct distribution name in the output you can use e.g.
echo "➥➥➥ Current System Is Based On $CURRENT_OS"
Edit:
This was not meant as a fix for a "typo" but my (possibly wrong) interpretation of the unclear question.
If you want to find a common criteria for Red Hat, Centos or Fedora, the existence of a file /etc/redhat-release might be an indication for this family of distributions as /etc/debian_version is an indication for a Debian based distribution (including e.g. Ubuntu). That means a check like
if [ -e /etc/redhat-release ]; then
echo "➥➥➥ Current system seems to be a distribution of the RedHat family"
# ...
fi
might do what you need.
Please clarify the question.
If you are only dealing with CentOS/Fedora/Red Hat you can use /etc/redhat-release to find which distribution it is, or also lsb_release -i instead of hostnamectl.
Also on Fedora and CentOS you usually also have fedora-release and centos-release files, in addition to redhat-release.
You can also grep ID from /etc/os-release.
[user#redhat8 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux release 8.1 (Ootpa)
[user#redhat8 ~]# lsb_release -i
Distributor ID: RedHatEnterprise
[user#redhat8 ~]# ls -l /etc/*release
-rw-r--r--. 1 root root 501 Sep 25 2019 /etc/os-release
-rw-r--r--. 1 root root 45 Sep 25 2019 /etc/redhat-release
lrwxrwxrwx. 1 root root 14 Sep 25 2019 /etc/system-release -> redhat-release
[user#redhat8 ~]# grep -w ID /etc/os-release
ID="rhel"
[user#centos7 ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
[root#centos7 ~]# lsb_release -i
Distributor ID: CentOS
[user#centos7 ~]# ls -l /etc/*release
-rw-r--r--. 1 root root 38 Nov 23 2018 /etc/centos-release
-rw-r--r--. 1 root root 393 Nov 23 2018 /etc/os-release
lrwxrwxrwx. 1 root root 14 Apr 15 09:05 /etc/redhat-release -> centos-release
lrwxrwxrwx. 1 root root 14 Apr 15 09:05 /etc/system-release -> centos-release
[user#centos7 ~]# grep -w ID /etc/os-release
ID="centos"
[user#Fedora ~]$ cat /etc/redhat-release
Fedora release 32 (Thirty Two)
[user#Fedora ~]$ lsb_release -i
Distributor ID: Fedora
[user#fedora ~]$ ls -l /etc/*release
lrwxrwxrwx. 1 root root 25 Jun 5 22:00 /etc/fedora-release -> ../usr/lib/fedora-release
lrwxrwxrwx. 1 root root 21 Jun 5 22:00 /etc/os-release -> ../usr/lib/os-release
lrwxrwxrwx. 1 root root 14 Jun 5 22:00 /etc/redhat-release -> fedora-release
lrwxrwxrwx. 1 root root 14 Jun 5 22:00 /etc/system-release -> fedora-release
[user#fedora ~]$ grep -w ID /etc/os-release
ID=fedora
You will need to have redhat-lsb-core package installed to have lsb_release command on Red Hat based distributions.

Grep command in linux

I need a little help to write a grep command in a single line to get first 15 files along with Size of the file in MB and sort by last modified time stamp.
if I execute below command
grep -il "SmapleString" *.log| xargs -t ls -ltr
Result:
-rw-r--r-- 1 Text1 Text2 5432278 27 mar 15:22 SampleFile.log
My Result:
grep -il "SmapleString" *.log| xargs -t ls -ltr| tr -s ' ' | cut -d' ' -f5-9|tail -r|head -15
5432278 27 mar 13:44 SampleFile.log
Required Output:
27 mar 13:44 SampleFile.log 5MB
OR
5MB 27 mar 13:44 SampleFile.log
please post your comments
You can try
ls -l -h -t | head -n 5
-t sort by modification time, newest first

Reading file in bash loop on AIX/bash is much slower than in Linux/ksh - BLOCKSIZE?

We have a custom script ( in ksh) which was developed in RHEL Linux.
The functionality is
1) Read the input ASCII file
2) Replace "\" with "\\" using sed -i inplace the files
3) Load the history file into memory
4) Compare the data with current day
5) Generate the net change records
During a platform upgrade, we had to migrate this script on AIX 7.1 and
replaced the ksh with bash since, typeset -A is not available on ksh AIX and sed -i command with perl -pi -e and the rest of the script is almost the same.
We observe that the script processes for 1 hour ( 691 files) in Linux but, in AIX it is taking 7+ hours for the same.
We observe for one input file the below snippet is having a performance difference, Linux code completes within 1-2 seconds whereas, in AIX it takes 13-15 seconds. Due to this performance difference for each file , for 691 files, the script is taking 7 hours to complete.
Could you please help me understand if we can tune this script for a better performance on AIX. Any pointers will be very helpful.
Thank you in advance for your help!
Adding test results below for more precise issue
Linux Test script:
#!/bin/sh
export LANG="C"
echo `date`
typeset -A Archive_Lines
if [ -f "8249cii1.ASC" ]
then
echo `date` Starting sed
sed -i 's/\\/\\\\/g' 1577cii1.ASC
echo `date` Ending sed
while read line; do
if [[ "${#line}" == "401" ]]
then
Archive_Lines["${line:0:19}""${line:27}"]="${line:27:10}"
else
echo ${#line}
fi
done < 1577cii1.ASC
echo `date` Starting sed
sed -i 's/\\\\/\\/g' 1577cii1.ASC
echo `date` Ending sed
fi
echo `date`
Linux execution:
ksh read4.sh
Sun Nov 12 15:03:18 CST 2017
Sun Nov 12 15:03:18 CST 2017 Starting sed
Sun Nov 12 15:03:19 CST 2017 Ending sed
402
405
403
339
403
403
Sun Nov 12 15:03:22 CST 2017 Starting sed
Sun Nov 12 15:03:23 CST 2017 Ending sed
Sun Nov 12 15:03:23 CST 2017
AIX Test Script:
#!/usr/bin/bash
export LANG="C"
echo `date`
typeset -A Archive_Lines
if [ -f "1577cii1.ASC" ]
then
echo `date` Starting perl
perl -pi -e 's/\\/\\\\/g' 1577cii1.ASC
echo `date` Ending perl
while read line; do
if [[ "${#line}" == "401" ]]
then
Archive_Lines["${line:0:19}""${line:27}"]="${line:27:10}"
else
echo ${#line}
fi
done < 1577cii1.ASC
echo `date` Starting perl
perl -pi -e 's/\\\\/\\/g' 1577cii1.ASC
echo `date` Ending perl
fi
echo `date`
AIX Test execution:
bash read_test.sh
Sun Nov 12 15:00:17 CST 2017
Sun Nov 12 15:00:17 CST 2017 Starting perl
Sun Nov 12 15:00:18 CST 2017 Ending perl
402
405
313
403
337
403
403
Sun Nov 12 15:01:29 CST 2017 Starting perl
Sun Nov 12 15:01:29 CST 2017 Ending perl
Sun Nov 12 15:01:29 CST 2017
Replacing Archive_Lines["${line:0:19}""${line:27}"]="${line:27:10}" with echo"."
bash read_test.sh
Sun Nov 12 16:56:27 CST 2017
Sun Nov 12 16:56:27 CST 2017 Starting perl
Sun Nov 12 16:56:27 CST 2017 Ending perl
.
.
.
.
.
Sun Nov 12 16:56:42 CST 2017 Starting perl
Sun Nov 12 16:56:42 CST 2017 Ending perl
Sun Nov 12 16:56:42 CST 2017
With Archive_Lines["${line:0:19}""${line:27}"]="${line:27:10}"
bash read_test.sh
Sun Nov 12 16:59:52 CST 2017
Sun Nov 12 16:59:52 CST 2017 Starting perl
Sun Nov 12 16:59:52 CST 2017 Ending perl
402
405
313
403
337
403
403
Sun Nov 12 17:01:11 CST 2017 Starting perl
Sun Nov 12 17:01:11 CST 2017 Ending perl
Sun Nov 12 17:01:11 CST 2017
Thanks,
Vamsi
As Walter had suggested, it looks like there are some performance hits in bash for the substring processing (and possibly the length test).
It might be of interest to see what kind of timings you get with other solutions.
Here's a simplistic awk solution that should do the same thing as the original bash/substring logic (using your current sample data file; sans the output of line lengths != 401):
awk 'length($0)==401 { print substr($0,1,20)substr($0,28)"|"substr($0,28,10) }' 1577cii1.ASC | \
while IFS="|" read idx val
do
Archive_Lines["${idx}"]="${val}"
done
length($0)==401 : if line length is 401 then ...
print ...."|" ... : print 2 sections of output/fields separated by a pipe (|), where the fields are ...
substr($0,1,20)substr($0,28) : equivalent to your ${line:0:19}${line:27}
substr($0,28,10) : equivalent to your ${line:27:10}
at this point every line of length 401 is generating output like string1|string2
while IFS="|" read idx val : split the input back out into 2 variables ...
Archive_Lines["${idx}"]="${val}" : use the 2 variables as the array index/value pairs
NOTE: The addition of the pipe (|) as a field separator was added in case your substrings could include spaces; and of course if your substrings could include the pipe (|) then replace with some other character that won't show up in your substrings and which you can use as a field delimiter.
The objective is to see if awk's built-in length/substring processing is faster than bash's length/substring processing ...
This solved my problem
#!/usr/bin/ksh93
export LANG="C"
echo `date`
typeset -A Archive_Lines
if [ -f "1577cii1.ASC" ]
then
echo `date` Starting perl
perl -pi -e 's/\\/\\\\/g' 1577cii1.ASC
echo `date` Ending perl
while read line; do
if [[ "${#line}" == "401" ]]
then
Archive_Lines[${line:0:19}${line:27}]="${line:27:10}"
else
echo ${#line}
fi
done < 1577cii1.ASC
echo `date` Starting perl
perl -pi -e 's/\\\\/\\/g' 1577cii1.ASC
echo `date` Ending perl
fi
echo `date`
ksh93 read_test3.sh
Sun Nov 12 19:19:34 CST 2017
Sun Nov 12 19:19:34 CST 2017 Starting perl
Sun Nov 12 19:19:34 CST 2017 Ending perl
402
405
403
339
403
403
Sun Nov 12 19:19:38 CST 2017 Starting perl
Sun Nov 12 19:19:39 CST 2017 Ending perl
Sun Nov 12 19:19:39 CST 2017

bash script not running as expected from cron vs. shell.

I have a script I got from this website and modified to suit my needs. Orginal post: Linux Script to check if process is running & act on the result
When running the script from cron, it always creates a new process. If I run it from shell it runs normally. Can anyone help me debug the issue ?
Script
[root#server2 ~]# cat /root/full-migrate.sh
#!/bin/bash
case "$(pidof perl | wc -w)" in
0) echo "Restarting iu-maildirtoimap: $(date)" >> /var/log/iu-maildirtoimap.txt
/usr/local/bin/iu-maildirtoimap -i currentuser.txt -D imap.gmail.com:993 -d -n7 -I&
;;
1) echo "Everything seems okay: $(date)" >> /var/log/iu-maildirtoimap.txt
;;
*) echo "Removed double iu-maildirtoimap: $(date)" >> /var/log/iu-maildirtoimap.txt
kill -9 $(pidof perl | awk '{print $1}')
;;
esac
crontab job
[root#server2 ~]# crontab -l
*/1 * * * * /bin/bash /root/full-migrate.sh
From the logfile:
Removed double iu-maildirtoimap: Tue Dec 30 02:32:37 GMT 2014
Removed double iu-maildirtoimap: Tue Dec 30 02:32:38 GMT 2014
Removed double iu-maildirtoimap: Tue Dec 30 02:32:39 GMT 2014
Everything seems okay: Tue Dec 30 02:32:39 GMT 2014
Restarting iu-maildirtoimap: Tue Dec 30 02:33:01 GMT 2014
Restarting iu-maildirtoimap: Tue Dec 30 02:34:01 GMT 2014
Restarting iu-maildirtoimap: Tue Dec 30 02:35:01 GMT 2014
The first 4 entries are me manually running "/bin/bash /root/full-migrate.sh"
The last 3 are from the crontab.
Any suggestions on how to debug this issue ?
At the time of writing:
[root#server2 ~]# $(pidof perl | wc -w)
bash: 13: command not found
[root#server2 ~]# $(pidof perl | awk '{print $1}')
bash: 26370: command not found
Your test from the command line is not valid, because you are basically executing the process id, which will give you a command not found.
From the command line you will need to test this way:
$ pidof perl | wc -l
without the $()
The issue you are most likely having is that cron cannot find pidof in the path. So you will need to figure out where pidof resides on your system:
$ which pidof
and then put that full path in your cron job and it should work.

How to check syslog in Bash on Linux?

In C we log this way:
syslog( LOG_INFO, "proxying %s", url );
In Linux how can we check the log?
How about less /var/log/syslog?
On Fedora 19, it looks like the answer is /var/log/messages. Although check /etc/rsyslog.conf if it has been changed.
By default it's logged into system log at /var/log/syslog, so it can be read by:
tail -f /var/log/syslog
If the file doesn't exist, check /etc/syslog.conf to see configuration file for syslogd.
Note that the configuration file could be different, so check the running process if it's using different file:
# ps wuax | grep syslog
root /sbin/syslogd -f /etc/syslog-knoppix.conf
Note: In some distributions (such as Knoppix) all logged messages could be sent into different terminal (e.g. /dev/tty12), so to access e.g. tty12 try pressing Control+Alt+F12.
You can also use lsof tool to find out which log file the syslogd process is using, e.g.
sudo lsof -p $(pgrep syslog) | grep log$
To send the test message to syslogd in shell, you may try:
echo test | logger
For troubleshooting use a trace tool (strace on Linux, dtruss on Unix), e.g.:
sudo strace -fp $(cat /var/run/syslogd.pid)
A very cool util is journalctl.
For example, to show syslog to console: journalctl -t <syslog-ident>, where <syslog-ident> is identity you gave to function openlog to initialize syslog.
tail -f /var/log/syslog | grep process_name
where process_name is the name of the process we are interested in
If you like Vim, it has built-in syntax highlighting for the syslog file, e.g. it will highlight error messages in red.
vi +'syntax on' /var/log/syslog
On some Linux systems (e.g. Debian and Ubuntu) syslog is rotated daily and you have multiple log files where two newest files are uncompressed while older ones are compressed:
$ ls -l /var/log/syslog*
-rw-r----- 1 root adm 888238 Aug 25 12:02 /var/log/syslog
-rw-r----- 1 root adm 1438588 Aug 25 00:05 /var/log/syslog.1
-rw-r----- 1 root adm 95161 Aug 24 00:07 /var/log/syslog.2.gz
-rw-r----- 1 root adm 103829 Aug 23 00:08 /var/log/syslog.3.gz
-rw-r----- 1 root adm 82679 Aug 22 00:06 /var/log/syslog.4.gz
-rw-r----- 1 root adm 270313 Aug 21 00:10 /var/log/syslog.5.gz
-rw-r----- 1 root adm 110724 Aug 20 00:09 /var/log/syslog.6.gz
-rw-r----- 1 root adm 178880 Aug 19 00:08 /var/log/syslog.7.gz
To search all the syslog files you can use the following commands:
$ sudo zcat -f `ls -tr /var/log/syslog*` | grep -i error | less
where zcat first decompresses and prints all syslog files (oldest first), grep makes a search and less is paging the results of the search.
To do the same but with the lines prefixed with the name of the syslog file you can use zgrep:
$ sudo zgrep -i error `ls -tr /var/log/syslog*` | less
$ zgrep -V | grep zgrep
zgrep (gzip) 1.6
In both cases sudo is required if syslog files are not readable by ordinary users.

Resources