I want to write a script to find the latest version of rpm of a given package available from a mirror for eg: http://mirror.centos.org/centos/5/updates/x86_64/RPMS/
The script should be able to run on majority of linux flavors (eg centos, redhat, ubuntu). So yum based solution is not an option. Is there any existing script that does this? Or can someone give me a general idea on how to go about this?
Thx to levislevis85 for the wget cli. Try this:
ARCH="i386"
PKG="pidgin-devel"
URL=http://mirror.centos.org/centos/5/updates/x86_64/RPMS
DL=`wget -O- -q $URL | sed -n 's/.*rpm.>\('$PKG'.*'$ARCH'.rpm\).*/\1/p' | sort | tail -1`
wget $URL/$DL
I Will put my comment here, otherwise the code will not be readable.
Try this:
ARCH="i386"
PKG="pidgin-devel"
URL=http://mirror.centos.org/centos/5/updates/x86_64/RPMS
DL=`wget -O- -q $URL | sed -n 's/.*rpm.>\('$PKG'.*'$ARCH'.rpm\).*<td align="right">\(.*\)-\(.*\)-\(.*\) \(..\):\(..\) <\/td><td.*/\4 \3 \2 \5 \6 \1/p' | sort -k1n -k2M -k3n -k4n -k5n | cut -d ' ' -f 6 | tail -1`
wget $URL/$DL
What it does is:
wget - get the index file
sed - cut out some parts and put it together in different order. Should result in Year Month Day Hour Minute and Package, like:
2009 Oct 27 01 14 pidgin-devel-2.6.2-2.el5.i386.rpm
2009 Oct 30 10 49 pidgin-devel-2.6.3-2.el5.i386.rpm
sort - order the columns n stays for numerical and M for month
cut - cut out the filed 6
tail - show only last entry
the problem with this could be, if some older package release comes after a newer then this script will also fail. If the output of the site changes, the script will fail. There are always a lot of points where a script could fail.
using wget and gawk
#!/bin/bash
pkg="kernel-headers"
wget -O- -q http://mirror.centos.org/centos/5/updates/x86_64/RPMS | awk -vpkg="$pkg" 'BEGIN{
RS="\n";FS="</a>"
z=split("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec",D,"|")
for(i=1;i<=z;i++){
date[D[i]]=sprintf("%02d",i)
}
temp=0
}
$1~pkg{
p=$1
t=$2
gsub(/.*href=\042/,"",p)
gsub(/\042>.*/,"",p)
m=split(t,timestamp," ")
n=split(timestamp[1],d,"-")
q=split(timestamp[2],hm,":")
datetime=d[3]date[d[2]]d[1]hm[1]hm[2]
if ( datetime >= temp ){
temp=datetime
filepkg = p
}
}
END{
print "Latest package: "filepkg", date: ",temp
}'
an example run of the above:
linux$ ./findlatest.sh
Latest package: kernel-headers-2.6.18-164.6.1.el5.x86_64.rpm, date: 200911041457
Try this (which requires lynx):
lynx -dump -listonly -nonumbers http://mirror.centos.org/centos/5/updates/x86_64/RPMS/ |
grep -E '^.*xen-libs.*i386.rpm$' |
sort --version-sort |
tail -n 1
If your sort doesn't have --version-sort, then you'll have to parse the version out of the filename or hope that a regular sort will do the right thing.
You may be able to do something similar with wget or curl or even a Bash script using redirections with /dev/tcp/HOST/PORT. The problem with these is that you would then have to parse HTML.
Related
Does anyone know of any possible way to determine or glean this information from the terminal (in order to use in a bash shell script)?
On my Macbook Air, via the GUI I can go to "About this mac" > "Displays" and it tells me:
Built-in Display, 13-inch (1440 x 900)
I can get the screen resolution from the system_profiler command, but not the "13-inch" bit.
I've also tried with ioreg without success. Calculating the screen size from the resolution is not accurate, as this can be changed by the user.
Has anyone managed to achieve this?
I think you could only get the display model-name which holds a reference to the size:
ioreg -lw0 | grep "IODisplayEDID" | sed "/[^<]*</s///" | xxd -p -r | strings -6 | grep '^LSN\|^LP'
will output something like:
LP154WT1-SJE1
which depends on the display manufacturer. But as you can see the first three numbers in this model name string imply the display-size: 154 == 15.4''
EDIT
Found a neat solution but it requires an internet connection:
curl -s http://support-sp.apple.com/sp/product?cc=`system_profiler SPHardwareDataType | awk '/Serial/ {print $4}' | cut -c 9-` |
sed 's|.*<configCode>\(.*\)</configCode>.*|\1|'
hope that helps
The next script:
model=$(system_profiler SPHardwareDataType | \
/usr/bin/perl -MLWP::Simple -MXML::Simple -lane '$c=substr($F[3],8)if/Serial/}{
print XMLin(get(q{http://support-sp.apple.com/sp/product?cc=}.$c))->{configCode}')
echo "$model"
will print for example:
MacBook Pro (13-inch, Mid 2010)
Or the same without perl but more command forking:
model=$(curl -s http://support-sp.apple.com/sp/product?cc=$(system_profiler SPHardwareDataType | sed -n '/Serial/s/.*: \(........\)\(.*\)$/\2/p')|sed 's:.*<configCode>\(.*\)</configCode>.*:\1:')
echo "$model"
It is fetched online from apple site by serial number, so you need internet connection.
I've found that there seem to be several different Apple URLs for checking this info. Some of them seem to work for some serial numbers, and others for other machines.
e.g:
https://selfsolve.apple.com/wcResults.do?sn=$Serial&Continue=Continue&num=0
https://selfsolve.apple.com/RegisterProduct.do?productRegister=Y&country=USA&id=$Serial
http://support-sp.apple.com/sp/product?cc=$serial (last 4 digits)
https://selfsolve.apple.com/agreementWarrantyDynamic.do
However, the first two URLs are the ones that seem to work for me. Maybe it's because the machines I'm looking up are in the UK and not the US, or maybe it's due to their age?
Anyway, due to not having much luck with curl on the command line (The Apple sites redirect, sometimes several times to alternative URLs, and the -L option doesn't seem to help), my solution was to bosh together a (rather messy) PHP script that uses PHP cURL to check the serials against both URLs, and then does some regex trickery to report the info I need.
Once on my web server, I can now curl it from the terminal command line and it's bringing back decent results 100% of the time.
I'm a PHP novice so I won't embarrass myself by posting the script up in it's current state, but if anyone's interested I'd be happy to tidy it up and share it on here (though admittedly it's a rather long winded solution to what should be a very simple query).
This info really should be simply made available in system_profiler. As it's available through System Information.app, I can't see a reason why not.
Hi there for my bash script , under GNU/Linux : I make the follow to save
# Resolution Fix
echo `xrandr --current | grep current | awk '{print $8}'` >> /tmp/width
echo `xrandr --current | grep current | awk '{print $10}'` >> /tmp/height
cat /tmp/height | sed -i 's/,//g' /tmp/height
WIDTH=$(cat /tmp/width)
HEIGHT=$(cat /tmp/height)
rm /tmp/width /tmp/height
echo "$WIDTH"'x'"$HEIGHT" >> /tmp/Resolution
Resolution=$(cat /tmp/Resolution)
rm /tmp/Resolution
# Resolution Fix
and the follow in the same script for restore after exit from some app / game
in some S.O
This its execute command directly
ResolutionRestore=$(xrandr -s $Resolution)
But if dont execute call the variable with this to execute the varible content
$($ResolutionRestore)
And the another way you can try its with the follow for example
RESOLUTION=$(xdpyinfo | grep -i dimensions: | sed 's/[^0-9]*pixels.*(.*).*//' | sed 's/[^0-9x]*//')
VRES=$(echo $RESOLUTION | sed 's/.*x//')
HRES=$(echo $RESOLUTION | sed 's/x.*//')
OK I have always had this problem. I want JUST the available updates listed in a file via bash script from a Linux system (RHEL or Fedora) using yum but I always have to deal with the Header information created which looks like this:
Loaded plugins: XXXX-repo XXXX-updates
: WWWWWW-repo something-updates QQQQQ-updates
Updated packages
package1.i686 1:234 RHEL 6.5 updates
package2.i686 1:234 RHEL 6.5 updates
package3.i686 1-234 RHEL 6.5 updates
package4.noarch 1.234 RHEL 6.5 updates
All I want is a list of package1,package2, etc. which seems simple enough but it isn't because I can't just grep on "updates" or ":". Am I looking at this wrongly? Why would I not want to capture what updates were found in a script? Should I just update and check what has been updated instead? Thoughts?
PS> I can not use --noplugins option.
EDIT: So far I have come up with this,
sudo yum check-update | grep "\." | awk '(NR >=1) {print $1;}' | grep '^[[:alpha:]]'
Basically grab the lines with a period in them, the first line, and make sure it first contains alpha letters. Perhaps over done but it seems to work.
To only print lines following (but not including) "Updated packages"
yum check-update | awk 'p; /Updated packages/ {p=1}'
Note, on my Fedora system, a blank line separates the "header" from the list of updatable packages, so I would use awk 'p;/^$/{p=1}'
If you pipe the output above into awk using this command:
| awk '(NR >=4) {print $1;}'
You will get the following output
package1.i686
package2.i686
package3.i686
package4.noarch
The (NR >=4) tells awk to ignore the first three lines. The {print $1;} tells awk to print the first word of each line.
You can read here for more information on cutting stuff out after certain characters on each line.
You can then use sed if stripping out everything after the . is important
| awk '(NR >=4) {print $1;}' | sed s/\.[^\.]*$//
Gives the following output
package1
package2
package3
package4
Then pipe it into another sed command to replace the linebreaks with a comma.
| awk '(NR >=4) {print $1;}' | sed s/\.[^\.]*$// | sed ':a;N;$!ba;s/\n/,/g'
Yields the following output
package1,package2,package3,package4
A more flexible solution
The solution below does not assume a specific number of lines in the Header (Ex. in CentOS I got much more header lines).
Nor does it suppose that you are only interested in the repository updates.
yum check-update | awk '/\S+\s+[0-9]\S+\s+\S+/ {print $1 }' > updates
Example
For the following yum check-update output
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
epel/x86_64/metalink | 31 kB 00:00:00
* base: asi-fs-m.net
Excluding mirror: mirror.de.leaseweb.net
Excluding mirror: mirror.fra10.de.leaseweb.net
base | 3.6 kB 00:00:00
cwp | 2.9 kB 00:00:00
extras | 3.4 kB 00:00:00
mariadb | 2.9 kB 00:00:00
remi-safe | 3.0 kB 00:00:00
updates | 3.4 kB 00:00:00
remi-safe/primary_db | 1.4 MB 00:00:00
openvpn.x86_64 2.4.7-1.el7 epel
polkit.x86_64 0.112-18.el7_6.1 updates
pure-ftpd.x86_64 1.0.47-2.el7 epel
remi-release.noarch 7.6-2.el7.remi remi-safe
You can get
openvpn.x86_64
polkit.x86_64
pure-ftpd.x86_64
remi-release.noarch
Explanation
This solution assumes that the relevant lines have the pattern
<package name><spaces><version number><spaces><repo name>
If you want to output a particular repository, then use the pattern
/\S+\s+[0-9]\S+\s+repo_name/
PS:
If this solution does not work in your system, let me know in a comment
Try this:
yum check-update | awk '{if($5 ~ /updates/){print $1}}' | tr '\n' ','
If the input contains 'updates' on fifth column then print first column and create a csv list.
Isn't this easier:
yum check-update -q | awk '{print $1}'
Edited.
The explanation of the command:
yum check-update -p - will list the updates in a 3 column list which are package + new version + repository.
awk '{ print $1 }' - will pick up the first column ( package )
I'm trying to write a bash script that determines whether a RAR archive has more than one root file.
The unrar command provides the following type of output if I run it with the v option:
[...#... dir]$ unrar v my_archive.rar
UNRAR 4.20 freeware Copyright (c) 1993-2012 Alexander Roshal
Archive my_archive.rar
Pathname/Comment
Size Packed Ratio Date Time Attr CRC Meth Ver
-------------------------------------------------------------------------------
file1.foo
2208411 2037283 92% 08-08-08 08:08 .....A. 00000000 m3g 2.9
file2.bar
103 103 100% 08-08-08 08:08 .....A. 00000000 m0g 2.9
baz/file3.qux
9911403 9003011 90% 08-08-08 08:08 .....A. 00000000 m3g 2.9
-------------------------------------------------------------------------------
3 12119917 11040397 91%
and since RAR is proprietary I'm guessing this output is as close as I'll get.
If I can get just the file list part (the lines between ------), and then perhaps filter out all even lines or lines beginning with multiple spaces, then I could do num_root_files=$(list of files | cut -d'/' -f1 | uniq | wc -l) and see whether [ $num_root_files -gt 1 ].
How do I do this? Or is there a saner approach?
I have searched for and found ways to grep text between two words, but then I'd have to include those "words" in the command, and doing that with entire lines of dashes is just too ugly. I haven't been able to find any solutions for "grep text between lines beginning with".
What I need this for is to decide whether to create a new directory or not before extracting RAR archives.
The unrar program does provide the x option to extract with full path and e for extracting everything to the current path, but I don't see how that could be useful in this case.
SOLUTION using the accepted answer:
num_root_files=$(unrar v "$file" | sed -n '/^----/,/^----/{/^----/!p}' | grep -v '^ ' | cut -d'/' -f1 | uniq | wc -l)
which seems to be the same as the shorter:
num_root_files=$(unrar v "$file" | sed -n '/^----/,/^----/{/^----/!p}' | grep -v '^ ' | grep -c '^ *[^/]*$')
OR using 7z as mentioned in a comment below:
num_root_files=$(7z l -slt "$file" | grep -c 'Path = [^/]*$')
# check if value is gt 2 rather than gt 1 - the archive itself is also listed
Oh no... I didn't have a man page for unrar so I looked one up online, which seems to have lacked some options that I just discovered with unrar --help. Here's the real solution:
unrar vb "$file" | grep -c '^[^/]*$'
I haven't been able to find any solutions for "grep text between lines
beginning with".
In order to get the lines between ----, you can say:
unrar v my_archive.rar | sed -n '/^----/,/^----/{/^----/!p}'
So what I'm intending to do here is to determine the latest stable version of TuxOnIce from http://tuxonice.net/downloads/all/ (currently tuxonice-for-linux-3.8.0-2013-02-24.patch.bz2).
What complicates things is that there's no "current" link, so we gotta follow the versioning, which is something like (these don't exist):
tuxonice-for-linux-3.8.0-2013-4-2.patch.bz2
tuxonice-for-linux-3.8-4-2013-4-16.patch.bz2
tuxonice-for-linux-3.8-11-2013-5-23.patch.bz2
The problem is they're gonna be in this order:
tuxonice-for-linux-3.8-11-2013-5-23.patch.bz2
tuxonice-for-linux-3.8-4-2013-4-16.patch.bz2
tuxonice-for-linux-3.8.0-2013-4-2.patch.bz2
My current implemetation (which is garbage) is this. I thought about using the dates but couldn't figure out how to do that either (/tmp/tuxonice is the index file):
_major=3.8 # Auto-generated
_TOI=$(grep ${_major}-1[0-9] /tmp/tuxonice | cut -d '"' -f2 | tail -1)
[ ! $_TOI ] && _TOI=$(grep ${_major}- /tmp/tuxonice | cut -d '"' -f2 | tail -1)
[ ! $_TOI ] && _TOI=$(grep ${_major}.0-2 /tmp/tuxonice | cut -d '"' -f2 | tail -1)
Thanks.
Use the webserver's feature to sort the index page by modification date in reverse order, grab the page using lynx -dump, get the first line matching the filename you are interested in and print the respective column. This gives you the absolute URL to the file, from there you can tweak the command to give you the exact output you want (filename, just the version string, ...).
$ lynx -dump 'http://tuxonice.net/downloads/all/?C=M&O=D'|awk '/^[[:space:]]*[[:digit:]]+\..+\/tuxonice-for-linux/ { print $2; exit }'
http://tuxonice.net/downloads/all/tuxonice-for-linux-3.8.0-2013-02-24.patch.bz2
Still not super-robust and will obviously break if the modification dates are not as expected, and you probably also want to tweak the regex a bit to be more specific.
This isn't a real answer, but I thought this "one-liner"[1] was pretty cool:
HTML=$(wget -qO- http://tuxonice.net/downloads/all/ | grep tuxonice); TIMESTAMP=$(echo "$HTML" | sed 's/.*\([0-9]\{2\}-[A-Za-z]\{3\}-[0-9]\{4\} [0-9]\{2\}:[0-9]\{2\}\).*/\1/' | while read line; do echo $(date --date "$line" +%s) $line; done | sort | tail -n 1 | cut -d' ' -f2-3); LINK=$(echo "$HTML" | grep "$TIMESTAMP" | sed 's/.*href=\"\(.*\)\".*/\1/'); echo "http://tuxonice.net/downloads/all/${LINK}"
Prints:
http://tuxonice.net/downloads/all/tuxonice-for-linux-3.8.0-2013-02-24.patch.bz2
This approach is really just a joke though. Obviously, there are better ways to do this, perhaps using a scripting language that supports XML parsing.
At the very least, maybe this will give you some insight on how you can use the date/time values of the files to select the "newest". But I'd caution using this (because upload dates may not coincide with version numbers), and suggest that your version number idea was probably a better idea, if you can somehow handle all of the various naming and version numbering schemes it looks like they've used.
[1] It's not a real one liner
Edit: Translated
I have a RSS-feed that i want to parse. It's a podcast and I want just the MP3-urls to download them with wget.
This is the podcast: http://feeds.feedburner.com/Film-UndKino-trailerVideopodcast
The title should include an (de) to get just the german episodes.
The publish-date should be today.
Would be great if someone could help me – I came this far:
wget -q -O- view-source:http://feeds.feedburner.com/Film-UndKino-trailerVideopodcast?format=xml| awk 'BEGIN{RS=""}
/(date +'%d %M %Y')/{
gsub(/.*|.*/,"")
print
}
But it doesn't work.
Thanks in advance,
arneb3rt
You need to drop the "view-source:" from the wget command and execute the date command (with %b to print the abbreviated month instead of %M) outside of the awk command. The following bash script uses grep instead of awk to produce the URLs of where wget can fetch the podcasts.
Note that, probably due to the holidays, there have been no podcasts since 24 Dec 2011 at the feed, so I hard-coded the date of the last podcast for testing:
url='http://feeds.feedburner.com/Film-UndKino-trailerVideopodcast?format=xml'
d=$(date +'%d %b %Y')
d="24 Dec 2011"
echo "Checking podcasts for date: ${d}"
wget -q -O- ${url} |\
grep -A6 "(de)" |\
grep -A1 "${d}" |\
egrep -o 'http[^ ]*de.mp4' |\
sort | uniq
The output of the above bash script lists two URLs (one feedburner and the other iTunes):
Checking podcasts for date: 24 Dec 2011
http://feedproxy.google.com/~r/Film-UndKino-trailerVideopodcast/~5/pzeSvkVK-3A/trailer01_de.mp4
http://www.moviemaze-trailer.de/ipod/6841/trailer01_de.mp4
Therefore, you could wget the 24 Dec 2011 podcast from either of the above URLs.