{"id":941,"date":"2013-09-02T17:26:33","date_gmt":"2013-09-02T17:26:33","guid":{"rendered":"http:\/\/joelinoff.com\/blog\/?p=941"},"modified":"2014-03-31T19:12:10","modified_gmt":"2014-03-31T19:12:10","slug":"create-and-use-local-mirrored-yum-repository-for-centos-6-4-x86_64","status":"publish","type":"post","link":"https:\/\/joelinoff.com\/blog\/?p=941","title":{"rendered":"Create and use a local mirrored yum repository for CentOS 6.4 x86_64"},"content":{"rendered":"<p>A local mirrored yum repository is a copy of the standard yum repositories for CentOS that exists on your local network. It is kept up to date by synchronizing to an external site. If you have more than a few local hosts, using a local mirrored repo can significantly reduce internet traffic and speed up the update process.<\/p>\n<p>This blog describes how to create, sync, test and use a local mirrored repo for CentOS 6.4. You will be shown how to create the repo, keep it in sync using cron, test the implementation and how to update the \/etc\/yum.repos.d directory on each host. It also provides 4 bash scripts that you can customize for your site to make maintenance easier.<br \/>\n<!--more--><\/p>\n<h1>Contents<\/h1>\n<ul>\n<li><a href=\"#intro\">Introduction<\/a><\/li>\n<li><a href=\"#siteconfparams\">Site Configuration Parameters<\/li>\n<li><a href=\"#confsync\">Configuration and Synchronization Scripts\n<ul>\n<li><a href=\"#repo_conf\">repo_conf.sh<\/a><\/li>\n<li><a href=\"#repo_sync\">repo_sync.sh<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#init\">Initialize Your Mirrored Repository<\/li>\n<li><a href=\"#test\">Test Your Mirrored Repository\n<ul>\n<li><a href=\"#repo_test\">repo_test.sh<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#cron\">Cron the Synchronization<\/li>\n<li><a href=\"#use\">Use Your Mirrored Repository\n<ul>\n<li><a href=\"#repo_update\">repo_update.sh<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><a name=\"intro\"><\/a><\/p>\n<h1>Introduction<\/h1>\n<p>When you type &#8220;yum update&#8221; on a standard CentOS installation your site is updated from an external site that is randomly chosen from a list of mirrored repositories on the internet. The packages that need to be updated are detected by comparing version information from your site with the version information from the external site and then downloaded through the internet.<\/p>\n<p>For a small number of hosts this works really well because most packages are small and there normally only a few that are updated at a time but once your network grows to more that a small number of hosts, keeping them all in sync can result in a fair amount of internet traffic. <\/p>\n<p>Please note that the term &#8220;a small number of hosts&#8221; is deliberately vague. Some sites with a slow internet connection would probably see significant performance improvements once they reached 3 or 4 hosts whereas others with a very fast, fat pipe might not see any improvement until they had dozens of hosts. In my case I decided to switch over when I had about 20.<\/p>\n<p>To reduce the internet traffic overhead associated with updating multiple hosts on your network, you can create a local mirrored repository that acts just like an external repository (which is, itself, mirrored). If you have a large site with a fast, fat internet pipe you should consider becoming an external repository to help the community.<\/p>\n<p>This blog describes how to create the local repository, how to keep it synchronized, how to test it and how to update the \/etc\/yum.repos.d directories on your hosts to make it all work.<\/p>\n<p><a name=\"siteconfparams\"><\/a><\/p>\n<h1>Site Configuration Parameters<\/h1>\n<p>The first thing that you need to do is determine where you want the local repository to reside. It must be a network resource that is visible to all of the hosts that want to use it. I use an NFS mount. For the purposes of this discussion we will assume that the network path to the mirrored repository is &#8220;<code>\/shared\/repo\/<\/code>&#8220;.<\/p>\n<p>Second you need to choose an administrative host that can create\/update the repo directories and run the cron job to keep it in sync. For this discussion we will use the host &#8220;<code>bigbob<\/code>&#8220;.<\/p>\n<p>Finally you need to determine which repositories you want to mirror. That decision is going to be site dependent but for me I chose the centos_6.4_extras, centos_6.4_os, centos_6.4_updates and elrepo_el6 repositories. The repositories with the &#8220;centos_&#8221; prefix. The repository with the &#8220;elrepo_el6&#8221; prefix is from the <a href=\"http:\/\/elrepo.org\/tiki\/tiki-index.php\">elrepo<\/a> repository. It contains lots of useful stuff that is not in the standard release.<\/p>\n<blockquote><p>To see the repositories that you reference by default, take a look at the &#8220;<code>\/etc\/yum.repos.d\/*repo<\/code> files on your system.<\/p><\/blockquote>\n<p>Here is a summary of the site configuration:<\/p>\n<blockquote>\n<table>\n<tbody>\n<tr>\n<th>Network Path<\/th>\n<td><code>\/shared\/repo<\/code><\/td>\n<\/tr>\n<tr>\n<th>Admin Host<\/th>\n<td><code>bigbob<\/code><\/td>\n<\/tr>\n<tr>\n<th>Admin Path<\/th>\n<td><code>\/shared\/repo\/bin<\/code><\/td>\n<\/tr>\n<tr>\n<th>CentOS 5.4 Repos<\/th>\n<td><code>extras, os, updates<\/code><\/td>\n<\/tr>\n<tr>\n<th>Other Repos<\/th>\n<td><code><a href=\"http:\/\/elrepo.org\/tiki\/tiki-index.php\">elrepo<\/a><\/code><\/td>\n<\/tr>\n<tr>\n<th>Conf Script<\/th>\n<td><code>\/shared\/repo\/bin\/repo_conf.sh<\/code><\/td>\n<\/tr>\n<tr>\n<th>Sync Script<\/th>\n<td><code>\/shared\/repo\/bin\/repo_sync.sh<\/code><\/td>\n<\/tr>\n<tr>\n<th>Test Script<\/th>\n<td><code>\/shared\/repo\/bin\/repo_test.sh<\/code><\/td>\n<\/tr>\n<tr>\n<th>Update Script<\/th>\n<td><code>\/shared\/repo\/bin\/repo_update.sh<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/blockquote>\n<p><a name=\"confsync\"><\/a><\/p>\n<h1>Configuration and Synchronization Scripts<\/h1>\n<p>To configure your site, log into bigbob (your administrative host) and make sure that you have the createrepo package installed. You can do this by running the &#8220;<code>yum info createrepo<\/code>&#8221; to see if it is installed. If it is, then you are good to go. If it isn&#8217;t then run &#8220;<code>yum install -y createrepo<\/code>&#8220;.<\/p>\n<p>After that create the <code>\/shared\/repo\/bin<\/code> directory so that you have a place to store the scripts and make sure the <code>\/shared\/repo<\/code> is available as an NFS mount (or automount). I am not going to describe how to create an NFS mount or automount for hosts on your site. It is a complex topic and there are many great resources available on the web.<\/p>\n<p><a name=\"repo_conf\"><\/a><\/p>\n<h2>repo_conf.sh<\/h2>\n<p>Now you need to create the site configuration file. This is a simple bash script that is used by the other scripts to get basic configuration information such as where the repo is located.<\/p>\n<p>[crayon lang=&#8221;bash&#8221; toolbar=&#8221;always&#8221; title=&#8221;repo_conf.sh&#8221;]<br \/>\n#!\/bin\/bash<\/p>\n<p>#<br \/>\n# Keep my local CentOS 6.4 repo mirror up to date. The local repo<br \/>\n# mirror is used by all CentOS 6.4 hosts on the internal nework.<br \/>\n#<br \/>\nmirror_repo=&#8221;\/shared\/repo&#8221;<br \/>\nif [ ! -d $mirror_repo ] ; then<br \/>\n    echo &#8220;ERROR: mirror repo directory does not exist: $mirror_repo&#8221;<br \/>\n    exit 1<br \/>\nfi<\/p>\n<p>#<br \/>\n# This is the generated repo file that is used in the<br \/>\n# \/etc\/yum.repos.d directory.<br \/>\n#<br \/>\nmirror_repo_file=&#8221;$mirror_repo\/yum.repos.d\/local.repo&#8221;<\/p>\n<p>#<br \/>\n# This is the test directory.<br \/>\n#<br \/>\nmirror_repo_test=&#8221;$mirror_repo\/test&#8221;<br \/>\n[\/crayon]<\/p>\n<p><a name=\"repo_sync\"><\/a><\/p>\n<h2>repo_sync.sh<\/h2>\n<p>Finally you need to create the synchronization script. This script also creates the mirror. <\/p>\n<p>You will need to update the <code>list<\/code> variable at line 55 to change the external reference to an rsync site near you.<\/p>\n<p>You will also need to update the <code>excludes<\/code> variable at line 66 to define which packages you wish to exclude. By default all packages are included.<\/p>\n<p>[crayon lang=&#8221;bash&#8221; toolbar=&#8221;always&#8221; title=&#8221;repo_sync.sh&#8221;]<br \/>\n#!\/bin\/bash<\/p>\n<p>#<br \/>\n# Keep the local mirror repo in sync with the external repo.<br \/>\n# This can be run in a cron jobs as follows:<br \/>\n#<br \/>\n#    # Update once per day at 10:00PM.<br \/>\n#    0 22 * * * \/shared\/repo\/bin\/repo_sync.sh<br \/>\n#<br \/>\n# The configuration information is \/shared\/repo\/bin\/repo_conf.sh.<br \/>\n#<br \/>\numask 0<\/p>\n<p>#<br \/>\n# Keep my local CentOS 6.4 repo mirror up to date. The local repo<br \/>\n# mirror is used by all CentOS 6.4 hosts on the internal nework.<br \/>\n#<br \/>\nmedir=$(dirname &#8212; $(readlink -f $0))<br \/>\nif [ -f &#8220;$medir\/repo_conf.sh&#8221; ] ; then<br \/>\n    . $medir\/repo_conf.sh<br \/>\nelse<br \/>\n    echo &#8220;ERROR: missing file: $medir\/repo_conf.sh.&#8221;<br \/>\n    exit 1<br \/>\nfi<br \/>\nif [[ &#8220;$mirror_repo&#8221; == &#8220;&#8221; ]] ; then<br \/>\n    echo &#8220;ERROR: mirror_repo not defined.&#8221;<br \/>\n    exit 1<br \/>\nfi<br \/>\nif [[ &#8220;$mirror_repo_file&#8221; == &#8220;&#8221; ]] ; then<br \/>\n    echo &#8220;ERROR: mirror_repo_file not defined.&#8221;<br \/>\n    exit 1<br \/>\nfi<\/p>\n<p># Semaphore file used to avoid collisions.<br \/>\nsemaphore=&#8221;$mirror_repo\/.busy&#8221;<br \/>\nif [ -f $semaphore ] ; then<br \/>\n    echo &#8220;WARNING: sync already running: $(cat $semaphore)&#8221;<br \/>\n    exit 0<br \/>\nfi<br \/>\necho &#8220;pid=$$, host=$(hostname -f), user=$(whoami), date=&#8217;$(date)&#8217;, sem=$semaphore&#8221; >$semaphore<br \/>\nchmod a+rw $semaphore<\/p>\n<p># Trap ^C interrupt.<br \/>\nfunction keyboard_interrupt() {<br \/>\n    echo<br \/>\n    echo &#8220;^C interrupt, exiting&#8230;&#8221;<br \/>\n    rm -f $semaphore<br \/>\n    exit 1<br \/>\n}<br \/>\ntrap keyboard_interrupt SIGINT<\/p>\n<p># Emulate a 2D array.<br \/>\n# The first entry is the source, the second is the dst.<br \/>\n# Note that the trailing backslashes are important to rsync.<br \/>\nlist=(<br \/>\n    # First pair.<br \/>\n    &#8220;rsync:\/\/mirrors.cat.pdx.edu\/centos\/6.4\/&#8221;<br \/>\n    &#8220;${mirror_repo}\/centos\/6.4\/&#8221;<\/p>\n<p>    # Second pair.<br \/>\n    # URL: http:\/\/elrepo.org\/tiki\/Download<br \/>\n    ##! &#8220;rsync:\/\/mirrors.thzhost.com\/elrepo\/elrepo\/el6\/x86_64\/&#8221;<br \/>\n    &#8216;rsync:\/\/mirrors.neterra.net\/elrepo\/elrepo\/el6\/x86_64\/&#8217;<br \/>\n    &#8220;${mirror_repo}\/elrepo\/el6\/x86_64\/&#8221;<br \/>\n)<\/p>\n<p># Packages to exclude.<br \/>\nexcludes=(<br \/>\n    &#8216;local_centos_6.4_xen4_x86_64&#8217;<br \/>\n    &#8216;local_centos_6.4_centosplus_x86_64&#8217;<br \/>\n    &#8216;local_centos_6.4_fasttrack_x86_64&#8217;<br \/>\n)<\/p>\n<p># Iterate over the pairs and rsync.<br \/>\n# Note the bandwidth is limited to be a good citizen.<br \/>\n# Also note that there is some trickiness where I used the &#8211;filter<br \/>\n# option because the equivalent &#8211;exclude command didn&#8217;t work.<br \/>\nlen=$(( ${#list[@]} \/ 2 &#8211; 1 ))<br \/>\nfor i in $(seq 0 $len) ; do<br \/>\n    srcidx=$(( $i * 2 ))<br \/>\n    src=${list[$srcidx]}<\/p>\n<p>    dstidx=$(( $srcidx + 1 ))<br \/>\n    dst=${list[$dstidx]}<\/p>\n<p>    echo<br \/>\n    echo &#8216;# ================================================================&#8217;<br \/>\n    echo &#8216;# rsync&#8217;<br \/>\n    echo &#8220;#   src: $src&#8221;<br \/>\n    echo &#8220;#   dst: $dst&#8221;<br \/>\n    echo &#8216;# ================================================================&#8217;<br \/>\n    if [ ! -d $dst ] ; then<br \/>\n\tmkdir -p $dst<br \/>\n    fi<br \/>\n    rsync -avzP \\<br \/>\n\t&#8211;delete \\<br \/>\n\t&#8211;bwlimit=1024 \\<br \/>\n\t&#8211;prune-empty-dirs \\<br \/>\n\t&#8211;include=&#8217;*.rpm&#8217; \\<br \/>\n\t&#8211;exclude=&#8217;i386&#8242; \\<br \/>\n\t&#8211;exclude=&#8217;repodata&#8217; \\<br \/>\n\t&#8211;filter=&#8217;-! *\/&#8217; \\<br \/>\n\t$src $dst<br \/>\ndone<\/p>\n<p># Now create the yum repo data.<br \/>\nmirrored_pkgs=$(find $mirror_repo -type d -name x86_64)<br \/>\nfor mirrored_pkg in ${mirrored_pkgs[@]}; do<br \/>\n    echo<br \/>\n    echo &#8216;# ================================================================&#8217;<br \/>\n    echo &#8220;# createrepo &#8211;update $mirrored_pkg&#8221;<br \/>\n    echo &#8216;# ================================================================&#8217;<br \/>\n    createrepo &#8211;pretty &#8211;workers 4 &#8211;update $mirrored_pkg<br \/>\ndone<\/p>\n<p>echo<br \/>\necho &#8216;# ================================================================&#8217;<br \/>\necho &#8220;# creating $mirror_repo\/yum.repos.d\/local.repo&#8221;<br \/>\necho &#8216;# ================================================================&#8217;<br \/>\nlocal_repo=&#8221;$mirror_repo_file&#8221;<br \/>\nlocal_repo_dir=$(dirname &#8212; $local_repo)<br \/>\nif [ ! -d $local_repo_dir ] ; then<br \/>\n    mkdir -p $local_repo_dir<br \/>\nfi<br \/>\nif [ -f $local_repo ] ; then<br \/>\n    rm -f ${local_repo}<br \/>\nfi<br \/>\noffset=$(( ${#mirror_repo} + 2))<br \/>\ni=0<br \/>\nfor mirrored_pkg in ${mirrored_pkgs[@]}; do<br \/>\n    #echo $mirrored_pkg<br \/>\n    title=$(echo $mirrored_pkg | cut -c ${offset}- | tr &#8216;\/&#8217; &#8216;_&#8217;)<br \/>\n    if (( $i > 0 )) ; then<br \/>\n\techo >>${local_repo}<br \/>\n    fi<br \/>\n    title=&#8221;local_$title&#8221;<br \/>\n    prefix=&#8221;<br \/>\n    for exclude in ${excludes[@]}; do<br \/>\n\tif [[ &#8220;$exclude&#8221; == &#8220;$title&#8221; ]] ; then<br \/>\n\t    prefix=&#8217;##!&#8217;<br \/>\n\tfi<br \/>\n    done<br \/>\n    cat >>${local_repo} <<EOF\n${prefix}[$title]\n${prefix}name=$title\n${prefix}baseurl=file:\/\/$mirrored_pkg\n${prefix}gpgcheck=0\n${prefix}enabled=1\nEOF\n    i=$(( $i + 1 ))\ndone\n\necho\necho '# ================================================================'\necho \"# available repos\"\necho '# ================================================================'\nfor mirrored_pkg in ${mirrored_pkgs[@]}; do\n    echo $mirrored_pkg\ndone\necho\necho \"local_repo_file: $local_repo\"\n\nrm -f $semaphore\n\necho\necho \"repo_sync done\"\n[\/crayon]\n\n<a name=\"init\"><\/a><\/p>\n<h1>Initialize Your Mirrored Repository<\/h1>\n<p>Run the <code>\/shared\/repo\/bin\/repo_sync.sh<\/code> script to create the local mirrored repository. When this script finishes the following top level directories will have been created.<\/p>\n<blockquote>\n<table>\n<tbody>\n<tr>\n<td><code>\/shared\/repo\/centos<\/code><\/td>\n<td>The CentOS 6.4 repositories.<\/td>\n<\/tr>\n<tr>\n<td><code>\/shared\/repo\/elrepo<\/code><\/td>\n<td>The elrepo repositories.<\/td>\n<\/tr>\n<tr>\n<td><code>\/shared\/repo\/yum.repos.d<\/code><\/td>\n<td>The local.repo configuration for each host.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/blockquote>\n<p>At this point the mirrored repository only exists on disk. It is not used.<\/p>\n<p><a name=\"test\"><\/a><\/p>\n<h1>Test Your Mirrored Repository<\/h1>\n<p>Before putting the mirrored repository into production we need to test it. That is done by running the following test script to create dummy local installation and then running the &#8220;<code>yum list<\/code>&#8221; command.<\/p>\n<p>It works by creating <code>\/shared\/repo\/test<\/code> directory that contains a local yum configuration file and then running the yum list command with that information: &#8220;<code>yum -c yum.conf list<\/code>&#8220;.<\/p>\n<p><a name=\"repo_test\"><\/a><\/p>\n<h2>repo_test.sh<\/h2>\n<p>[crayon lang=&#8221;bash&#8221; toolbar=&#8221;always&#8221; title=&#8221;repo_test.sh&#8221;]<br \/>\n#!\/bin\/bash<\/p>\n<p>#<br \/>\n# Test the installation by creating a local<br \/>\n# yum configuration.<br \/>\n#<br \/>\nmedir=$(dirname &#8212; $(readlink -f $0))<br \/>\nif [ -f &#8220;$medir\/repo_conf.sh&#8221; ] ; then<br \/>\n    . $medir\/repo_conf.sh<br \/>\nelse<br \/>\n    echo &#8220;ERROR: missing file: $medir\/repo_conf.sh.&#8221;<br \/>\n    exit 1<br \/>\nfi<br \/>\nif [[ &#8220;$mirror_repo_test&#8221; == &#8220;&#8221; ]] ; then<br \/>\n    echo &#8220;ERROR: mirror_repo_test not defined.&#8221;<br \/>\n    exit 1<br \/>\nfi<br \/>\nif [[ &#8220;$mirror_repo_file&#8221; == &#8220;&#8221; ]] ; then<br \/>\n    echo &#8220;ERROR: mirror_repo_file not defined.&#8221;<br \/>\n    exit 1<br \/>\nfi<\/p>\n<p>if [ ! -f $mirror_repo_file ] ; then<br \/>\n    echo &#8220;ERROR: local repo file not found: $mirror_repo_file&#8221;<br \/>\n    exit 1<br \/>\nfi<\/p>\n<p>cd $mirror_repo_test<br \/>\ntest_path=$(readlink -f .)<br \/>\necho $test_path<\/p>\n<p>if [ ! -f &#8220;yum.conf&#8221; ] ; then<br \/>\n    cat >yum.conf <<EOF\n[main]\nreposdir=${test_path}\/yum.repos.d\npersistdir=${test_path}\/var\/lib\/yum\ncachedir=${test_path}\/var\/cache\/yum\/$basearch\/$releasever\nkeepcache=0\ndebuglevel=2\nlogfile=${test_path}\/var\/log\/yum.log\nexactarch=1\nobsoletes=1\ngpgcheck=1\nplugins=1\ninstallonly_limit=5\nbugtracker_url=http:\/\/bugs.centos.org\/set_project.php?project_id=16&#038;ref=http:\/\/bugs.centos.org\/bug_report_page.php?category=yum\ndistroverpkg=centos-release\nEOF\nfi\n\nif [ ! -d \"yum.repos.d\" ] ; then\n    mkdir yum.repos.d\nfi\n\ncp $mirror_repo_file yum.repos.d\/\nyum -c yum.conf list\n[\/crayon]\n\n<a name=\"cron\"><\/a><\/p>\n<h1>Cron the Synchronization<\/h1>\n<p>The repository that you are mirroring will change periodically as bug fixes are released and packages are enhanced. When those changes occur, you need to make sure that they are reflected at your site. You do this by creating a cron job that periodically run the \/shared\/repo\/bin\/repo_sync.sh script. <\/p>\n<blockquote><p><code>0 22 * * * cd \/shared\/repo\/bin && repo_sync.sh 2>cron.err 1>cron.out<\/code><\/p><\/blockquote>\n<p>As you can see, I do this once per day but that is probably overkill. You probably only need to do it weekly.<\/p>\n<p>Please note that some sites lock down the package versions that are available to avoid the risk of instability so they would not do this.<\/p>\n<p><a name=\"use\"><\/a><\/p>\n<h1>Use Your Mirrored Repository<\/h1>\n<p>At this point you have a fully functioning mirrored repository but no one is using it. To use it on a host you to do the following:<\/p>\n<ol>\n<li>Log onto the host.<\/li>\n<li>Create a backup of the <code>\/etc\/yum.repos.d<\/code> directory.<\/li>\n<li>Remove all of the files in <code>\/etc\/yum.repos.d<\/code> directory.<\/li>\n<li>Copy <code>\/shared\/repo\/yum.repos.d\/local.repo<\/code> to <code>\/etc\/yum.repos.d<\/code><\/li>\n<\/ol>\n<p><a name=\"repo_update\"><\/a><\/p>\n<h2>repo_update.sh<\/h2>\n<p>You can use this script (or a variant) to do this automatically. <\/p>\n<p>This script will automatically make a backup for your and it is re-entrant so it can be run it multiple times without causing problems because it will only update\/backup if something has changed.<\/p>\n<p>[crayon lang=&#8221;bash&#8221; toolbar=&#8221;always&#8221; title=&#8221;repo_update.sh&#8221;]<br \/>\n#!\/bin\/bash<\/p>\n<p>#<br \/>\n# This script will update a host so that it uses a the new local repo.<br \/>\n# It must be run as root.<br \/>\n#<br \/>\numask 0<\/p>\n<p>medir=$(dirname &#8212; $(readlink -f $0))<br \/>\nif [ -f &#8220;$medir\/repo_conf.sh&#8221; ] ; then<br \/>\n    . $medir\/repo_conf.sh<br \/>\nelse<br \/>\n    echo &#8220;ERROR: missing file: $medir\/repo_conf.sh.&#8221;<br \/>\n    exit 1<br \/>\nfi<br \/>\nif [[ &#8220;$mirror_repo&#8221; == &#8220;&#8221; ]] ; then<br \/>\n    echo &#8220;ERROR: mirror_repo not defined.&#8221;<br \/>\n    exit 1<br \/>\nfi<br \/>\nif [[ &#8220;$mirror_repo_file&#8221; == &#8220;&#8221; ]] ; then<br \/>\n    echo &#8220;ERROR: mirror_repo_file not defined.&#8221;<br \/>\n    exit 1<br \/>\nfi<\/p>\n<p>#<br \/>\n# First see if we need to do anything.<br \/>\n#<br \/>\nif [ -d \/etc\/yum.repos.d ] ; then<br \/>\n    if [ ! -w \/etc\/yum.repos.d ] ; then<br \/>\n\techo &#8220;ERROR: you do not have write permission for \/etc\/yum.repos.d&#8221;<br \/>\n\texit 1<br \/>\n    fi<br \/>\nfi<br \/>\nlocal_repo=&#8221;\/etc\/yum.repos.d\/$(basename $mirror_repo_file)&#8221;<br \/>\nnum=$(ls -1 \/etc\/yum.repos.d\/* | wc -l)<\/p>\n<p>if (( $num == 1 )) ; then<br \/>\n    # There is only one file in the depot.<br \/>\n    # It is ours?<br \/>\n    if [ -f $local_repo ] ; then<br \/>\n\t# It is, copy over the new one if it is different.<br \/>\n\tsum1=$(sum $mirror_repo_file | awk &#8216;{print $1}&#8217;)<br \/>\n\tsum2=$(sum $local_repo | awk &#8216;{print $1}&#8217;)<br \/>\n\tif (( $sum1 != $sum2 )) ; then<br \/>\n\t    cp -v $mirror_repo_file $local_repo<br \/>\n\tfi<br \/>\n\t# all done.<br \/>\n\texit 0<br \/>\n    fi<br \/>\nfi<\/p>\n<p>#<br \/>\n# Backup the current version and create the new one.<br \/>\n#<br \/>\nif [ -d &#8220;\/etc\/yum.repos.d&#8221; ] ; then<br \/>\n    dts=$(date +&#8217;%Y%m%d%H%M%S&#8217;)<br \/>\n    backup_dir=&#8221;\/etc\/yum.repos.d.backup.$dts&#8221;<br \/>\n    if [ -f $backup_dir ] ; then<br \/>\n\techo &#8220;ERROR: time stamped backup dir exists: $backup_dir&#8221;<br \/>\n\texit 1<br \/>\n    fi<br \/>\n    mv \/etc\/yum.repos.d $backup_dir<br \/>\nfi<\/p>\n<p>mkdir \/etc\/yum.repos.d<br \/>\nchmod 0755 \/etc\/yum.repos.d<br \/>\ncp -v $mirror_repo_file $local_repo<br \/>\n[\/crayon]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A local mirrored yum repository is a copy of the standard yum repositories for CentOS that exists on your local network. It is kept up to date by synchronizing to an external site. If you have more than a few local hosts, using a local mirrored repo can significantly reduce internet traffic and speed up &hellip; <a href=\"https:\/\/joelinoff.com\/blog\/?p=941\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Create and use a local mirrored yum repository for CentOS 6.4 x86_64<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[16],"tags":[35,34,33,36],"_links":{"self":[{"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/941"}],"collection":[{"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=941"}],"version-history":[{"count":39,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/941\/revisions"}],"predecessor-version":[{"id":1418,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/941\/revisions\/1418"}],"wp:attachment":[{"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=941"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=941"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/joelinoff.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=941"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}