Problem Description: An employee's linux system has a large number of duplicate software (different versions), resulting in errors when installing software using yum. Now we need to find out the duplicate software and delete the low version software. Execute rpm-qa | sort as follows:
[root@cws85 ~]# rpm -qa | sort a52dec-0.7.4-27.el7.x86_64 aalib-libs-1.4.0-0.22.rc5.el7.x86_64 abattis-cantarell-fonts-0.0.25-1.el7.noarch abrt-2.1.11-52.el7.centos.x86_64 abrt-addon-ccpp-2.1.11-52.el7.centos.x86_64 abrt-addon-kerneloops-2.1.11-52.el7.centos.x86_64 abrt-addon-pstoreoops-2.1.11-52.el7.centos.x86_64 abrt-addon-python-2.1.11-52.el7.centos.x86_64 abrt-addon-vmcore-2.1.11-52.el7.centos.x86_64 abrt-addon-xorg-2.1.11-52.el7.centos.x86_64 abrt-cli-2.1.11-52.el7.centos.x86_64 abrt-console-notification-2.1.11-52.el7.centos.x86_64 abrt-dbus-2.1.11-52.el7.centos.x86_64 abrt-desktop-2.1.11-52.el7.centos.x86_64 abrt-gui-2.1.11-52.el7.centos.x86_64 abrt-gui-libs-2.1.11-52.el7.centos.x86_64 abrt-java-connector-1.0.6-12.el7.x86_64 abrt-libs-2.1.11-52.el7.centos.x86_64 abrt-python-2.1.11-52.el7.centos.x86_64 abrt-retrace-client-2.1.11-52.el7.centos.x86_64 abrt-tui-2.1.11-52.el7.centos.x86_64 accountsservice-0.6.50-4.el7.1.x86_64 accountsservice-libs-0.6.50-4.el7.1.x86_64 acl-2.2.51-14.el7.x86_64 adcli-0.8.1-6.el7_6.1.x86_64 adwaita-cursor-theme-3.28.0-1.el7.noarch adwaita-gtk2-theme-3.28-2.el7.x86_64 adwaita-icon-theme-3.28.0-1.el7.noarch adwaita-qt5-1.0-1.el7.x86_64 aic94xx-firmware-30-6.el7.noarch alsa-firmware-1.0.28-2.el7.noarch alsa-lib-1.1.6-2.el7.x86_64 alsa-plugins-pulseaudio-1.1.6-1.el7.x86_64 alsa-tools-firmware-1.1.0-1.el7.x86_64 alsa-utils-1.1.6-1.el7.x86_64 anaconda-core-21.48.22.121-1.el7.centos.x86_64 anaconda-core-21.48.22.147-1.el7.centos.0.1.x86_64 anaconda-gui-21.48.22.147-1.el7.centos.0.1.x86_64 anaconda-tui-21.48.22.121-1.el7.centos.x86_64 #This is the low version of duplicate software. anaconda-tui-21.48.22.147-1.el7.centos.x86_64 #This is a high version of duplicate software. anaconda-widgets-21.48.22.147-1.el7.centos.0.1.x86_64 ..........ellipsis //A total of 2586 software
Requirements: As indicated above, you need to delete the lower version of the software, with the following exceptions:
[root@cws85 ~]# rpm -qa | grep audit-libs-[0-9]
audit-libs-2.8.4-4.el7.i686
audit-libs-2.8.4-4.el7.x86_64
Although it is duplicate software, one is x86_64 and the other is i686, so it can not be deleted, only the duplicate software at the end of _x86_64 can be deleted.
Arrays: Arrays are used in scripts. The following is a partial overview of arrays:
1. Array definition:
Declare-a array name# defines index arrays, subscripts start at 0
Declare-A array name # defines associative arrays, subscribed to arbitrary characters
2. Array assignment and replication:
2.1. Arrays can be assigned by command substitution: declare-a SOFT1= ($(rpm-qa | sort)# array SOFT1 holds all software
2.2. Array replication operation: Linux 2=(${linux 1 [@]}) array Linux 2 replicates the contents of array Linux 1
3. String operations of arrays:
3.1. String operators can be used on arrays, such as: ${string} for array ${array [@]}, and so on.
3.2. Array traversal: for i in ${!SOFT [@]} # Attention plus exclamation marks can traverse the values of the array, assuming that the maximum subscript of SOFT is 2586, the array can be traversed through the for loop, and the value of i is in turn from 0 to 2586.
The script content:
#!/bin/bash declare -a SOFT1=($(rpm -qa | sort)) #Array SOFT1 saves all software names for i in ${!SOFT1[*]} #Traversal array SOFT1 do declare -a SOFT2[$i]=${SOFT1[$i]%%-[0-9]*} #Array SOFT2 replicates part of the array SOFT1,%% is a string interception symbol, which is equivalent to removing the version number of the software, leaving only the name of the software. done for i in $(seq 0 $((${#SOFT2[@]}-1))) #Traversal array SOFT2 do let "j=$i+5" for (( ;i<j;j--)) #Jump out of the loop when i is less than j and execute the loop five times do if [ "${SOFT2[$i]}" == "${SOFT2[$j]}" ] #Test for duplicate software then declare -a SOFT3=($(rpm -qa | grep "^${SOFT2[$i]}-[0-9]" | sort)) #If the software is duplicated, perform rpm-qa | grep to duplicate the software name and assign it to the array SOFT3 if (( "${#SOFT3[@]}" < 2 )) #Check if the subscript number of SOFT3 array is less than 2 (with an additional layer of insurance) then echo "${SOFT2[$i]} no repeat version" >>/tmp/soft && continue #No duplicate version of the software is output less than 2 elif (( "${#SOFT3[@]}" > 2 )) #If the subscript is greater than 2, that is (rpm-qa | grep duplicate software) there are more than two software then X86=0 I686=0 #Initialize two variables for later comparison for i in ${!SOFT3[*]} #Traversal array SOFT3 do [[ "${SOFT3[$i]##*.}" == "i686" ]] && I686=$((I686+1)) || X86=$((X86+1)) #If the end of the software name is i686, then variable I686 plus 1, otherwise X86 plus 1 done (( "$X86" >= "$I686" )) && echo "${SOFT3[0]} can1 delete" >>/tmp/soft #If the X86 value is greater than I686, the output software can be deleted. elif (( "${#SOFT3[@]}" == 2 )) #If the subscript equals 2, there are two (rpm-qa | grep duplicate software) then [[ "${SOFT3[0]##*.}" == "i686" || "${SOFT3[1]##*.}" == "i686" ]] && { echo "${SOFT3[0]} only two packages but has I686" >>/tmp/soft ; continue ; } #As long as one of the two softwares ends with i686, the output cannot be deleted. echo "${SOFT3[0]} can2 delete" >>/tmp/soft fi fi done done
The script description:
1. Array SOFT1 preserves the full name of all software. Array SOFT2 intercepts the name of software without version name by array copy and string replacement, such as SOFT1 [4]=abrt-addon-ccpp-2.1.11-52.el7.centos.x86_64, SOFT2 [4]=abrt-addon-ccpp.
2. Use for loop traversal array SOFT2 to detect repetitive software, as follows:
for i in $(seq 0 $((${#SOFT2[@]}-1))) #Traversal array SOFT2 do let "j=$i+5" #j is 5 bigger than i. It is used to test whether a software name is equal to the five software names behind it. Because it is sorted by rpm-qa | sort, so the software names are arranged in alphabetical order. It is OK to compare five. for (( ;i<j;j--)) do if [ "${SOFT2[$i]}" == "${SOFT2[$j]}" ] #Compare duplicate software names
3. If there is duplication, we need to deal with the problem of software suffix names. Only duplicate software names ending with X86 can be output to delete the software. Use the array SOFT3=($(rpm-qa | grep"^${SOFT2 [$i]} - [0-9]" | sort)) to save the duplicate software searched, and then compare the results.
Output of the script: The output is redirected to a file, which reads as follows:
anaconda-core-21.48.22.121-1.el7.centos.x86_64 can2 delete anaconda-tui-21.48.22.121-1.el7.centos.x86_64 can2 delete audit-libs-2.8.4-4.el7.i686 only two packages but has I686 avahi-libs-0.6.31-17.el7.x86_64 can2 delete bzip2-libs-1.0.6-13.el7.i686 only two packages but has I686 copy-jdk-configs-2.2-5.el7_4.noarch can2 delete cracklib-2.9.0-11.el7.i686 only two packages but has I686 cryptsetup-libs-1.7.4-3.el7_4.1.x86_64 can2 delete dbus-1.10.24-13.el7_6.x86_64 can2 delete dbus-libs-1.10.24-13.el7_6.x86_64 can2 delete device-mapper-event-libs-1.02.149-10.el7_6.3.x86_64 can2 delete elfutils-libelf-0.172-2.el7.i686 only two packages but has I686 elfutils-libs-0.172-2.el7.i686 only two packages but has I686 fprintd-0.5.0-4.0.el7_0.x86_64 can2 delete freetype-2.8-12.el7_6.1.i686 only two packages but has I686 glib2-2.54.2-2.el7.x86_64 can2 delete glibc-2.17-260.el7_6.6.i686 only two packages but has I686 ........ellipsis //A total of 81 lines, 52 lines can be deleted (a few errors, explained later)
Script debugging information: sh-x script name shows part of the content as follows:
+ SOFT1=($(rpm -qa | sort)) #Array SOFT1 saves the complete software name ++ rpm -qa ++ sort + declare -a SOFT1 + for i in '${!SOFT1[*]}' #Traversal array SOFT1 + declare -a 'SOFT2[0]=a52dec' #Assign SOFT2 to the array, leaving only the software name + for i in '${!SOFT1[*]}' + declare -a 'SOFT2[1]=aalib-libs' + for i in '${!SOFT1[*]}' + declare -a 'SOFT2[2]=abattis-cantarell-fonts' + for i in '${!SOFT1[*]}' + declare -a 'SOFT2[3]=abrt' + for i in '${!SOFT1[*]}' + declare -a 'SOFT2[4]=abrt-addon-ccpp' + ..............Omitted, a total of 2586 ++ seq 0 2585 + for i in '$(seq 0 $((${#SOFT2[@]}-1)))' #Traverse the array SOFT2 and test which is duplicate software + let j=0+5 #A total of five comparisons + (( 1 )) + (( i<j )) + '[' a52dec == abrt-addon-kerneloops ']' + (( j-- )) + (( i<j )) + '[' a52dec == abrt-addon-ccpp ']' + (( j-- )) + (( i<j )) + '[' a52dec == abrt ']' + (( j-- )) + (( i<j )) + '[' a52dec == abattis-cantarell-fonts ']' + (( j-- )) + (( i<j )) + '[' a52dec == aalib-libs ']' #a53dec... is not a duplicate software + (( j-- )) + (( i<j )) + for i in '$(seq 0 $((${#SOFT2[@]}-1)))' #Compare the next, array subscript plus 1 + let j=1+5 ...........................................................................ellipsis + for i in '$(seq 0 $((${#SOFT2[@]}-1)))' + let j=35+5 #Array subscripts to 35 + (( 1 )) + (( i<j )) + '[' anaconda-core == anaconda-widgets ']' + (( j-- )) + (( i<j )) + '[' anaconda-core == anaconda-tui ']' + (( j-- )) + (( i<j )) + '[' anaconda-core == anaconda-tui ']' + (( j-- )) + (( i<j )) + '[' anaconda-core == anaconda-gui ']' + (( j-- )) + (( i<j )) + '[' anaconda-core == anaconda-core ']' #Find duplicate software here + SOFT3=($(rpm -qa | grep "^${SOFT2[$i]}-[0-9]" | sort)) #Array SOFT3 assignment = (rpm-qa | grep ^ anaconda-core - [0-9] | sort) ++ rpm -qa ++ sort ++ grep '^anaconda-core-[0-9]' + declare -a SOFT3 + (( 2 < 2 )) + (( 2 > 2 )) + (( 2 == 2 )) #There are just two bags. + [[ x86_64 == i686 ]] #The first package suffix is x86_64 + [[ x86_64 == i686 ]] #The second package suffix is x86_64 + echo 'anaconda-core-21.48.22.121-1.el7.centos.x86_64 can2 delete' #Output can be deleted + ..........................ellipsis
Script Output Errors: A total of 52 lines of script output files are deletable software, several of which are errors due to the name of the software, as follows:
Error 1: Software Name: Character-Number-Character-Version Number Causes Judgment Error
java-1.8.0-openjdk-1.8.0.222.b10-0.el7_6.x86_64 can1 delete
java-1.8.0-openjdk-1.8.0.222.b10-0.el7_6.x86_64 can1 delete
SOFT2 [$i]=${SOFT1 [$i]%-[0-9]*} # is the problem with intercepting software names, SOFT2=java, and the correct answer should be SOFT2=java-1.8.0-openjdk.
Error 2: The wrong software name ends with. X86 or something.
gpg-pubkey-0c1289c0-58c6ad7d can1 delete
gpg-pubkey-0c1289c0-58c6ad7d can1 delete
gpg-pubkey-0c1289c0-58c6ad7d can1 delete
When assigning values to SOFT1, you need to filter out software that does not end with. X86 or other suffixes.
Summary: Arrays are seldom used in scripts. This script deepens the understanding and application of arrays. Do not know how to solve the problem of error 1 in script output, most software can correctly remove version number, individual software name is not good, feel there will always be loopholes. The script is mainly used to practice the application of arrays, but also can find duplicate software from more than 2,000 software. Although there are individual errors, it is better than using eyes to find duplicate software. It is much easier to delete software by comparing output files.