I am maintaining a large number of wordpress installs on a production server, and we are looking to deploy InfiniteWP for managing these installs. I am looking for a way to script the distribution of the plugin folder to all of these installs.

On server wp-prod, all sites are stored in /srv/sitename/site/ The plugin needs to be copied from ~/iws-plugin to /srv/sitename/site/wp-content/plugins/

Here's some pseudo code to explain what I need to do:

array dirs = <all folders in /srv>
for each d in dirs
   if exits "/srv/d/site/wp-content/plugins"
     rsync -avzh --log-file=~/d.log ~/plugin_base_folder /srv/d/site/wp-content/plugins/
     touch d.log
     echo 'plugin folder for "d" not found' >> ~/d.log

I just don't know how to make it happen from the cli or via bash. I can (and will) tinker with a bash or ruby script on my test server, but I'm thinking the command-line-fu here on SF is strong enough to handle this issue much more quickly than I can hack together a solution.


2 Answers 2


ok here's some bash.. first, to get a list of all sites with plugin directories you can use globbing and ls -d (ie don't descend directory, give directory entry only)


for i in `ls -d /srv/*/site/wp-content/plugins`
   #whatever rsync command you want to do, $i will evaluate to the directory name
   e.g rsync -avzh /source/plugindir $i

#second pass to find all cases where the plugins directory does not exist.

LOGFILE = "/some/log"

    for i in ` ls -d /srv/*/site/wpcontent`
      if [ ! -d ${i}"/plugins" ]
         echo ${i}"is evil" > $LOGFILE

I ignored the part about having specialized rsync logfiles for each directory.. I wasn't sure what you meant by the path ~/d.log. you could do something with sed to change the slashes to dashes if you really wanted to have separate log files for rsync, or you could use awk and split out just the site name and use that as a base name for the log file. eg:

LOG=`echo $i | awk -F/ '{print $2}'`
  • This is exactly what I meant by "I feel like cli commands or a bash script could do this much more concisely". I'm going to test this out on a sandbox but it looks like this will do very much what I want. I should be able to use something like "--log-file=$i.log" to get rsync to spit out a log file with a name matching the subdir of /srv, so that I get a log for every rsync operation. Thanks!
    – Nick Abbey
    Jun 9, 2014 at 15:00
  • ok great, the problem with just using $i.log as the log file hame, is that in this example, $i evaluates to the full path of the matching directory, so now you have a really weird logfile location. IE you just put it in /srv/sitename/site/wpcontent.log Is that where you want it?
    – ssl
    Jun 11, 2014 at 6:34
  • You're correct, that's not quite where the log file belongs. Maybe in the future I will change it to use a single log file and have all of the rsync jobs just append to that file, but for now I'd like individual logs in ~/logs/*.log where * is the dir name that corresponds to the /srv sub dir being processed. I'm sure I can figure it out from here and will post any changes that I make to get it behaving the way I need. Thanks again!
    – Nick Abbey
    Jun 12, 2014 at 15:06

I had this written a few hours after the quetion was posted, but don't have the rep andwer my own question without waiting, so I'm posting it now. I feel like cli commands or a bash script could do this much more concisely, but this is what I wrote to do the job and it's pretty clear (even before I documented it so heavily)

Any feedback on this or alternative solutions will be greatly appreciated:

#!/usr/bin/env ruby

# rrdist.rb
# Utility script to copy the contents of a folder to multiple destinations
# ****LOCAL USE ONLY (FOR NOW)******
# TODO: Make it interactive (get source and destination via std in or file)
#       Make it work remotely (rsync over ssh)

require 'pathname'

#set the log folder location
log_folder = Pathname(File.expand_path('~')).join('logs')
#TODO: get this at runtime and validate it

#set the source folder
source_folder = Pathname(File.expand_path('~')).join('iwp-client')
#TODO: get this at runtime and validate it

#set the destination parent folder
dest_parent_folder = '/srv'
#TODO: get this at runtime and validate it

#get all the subfolders of the parent
target_dirs = Dir.glob('/srv/*')

#process each child folder
target_dirs.each do |folder|
    #first, build the destination string for the rsync command
    destination = "#{folder}/site/wp-content/plugins/"

        #set up the name of the log file
        vhost = (Pathname(folder).each_filename.to_a)[1]
    #TO-DO: If the destination is gotten at run time, then this will not work - FIX IT!

    #set up the actual log
    log = "#{log_folder}/#{vhost}.rrdist.log"

    #make sure the destination exists!
    if  File.directory?(destination)
        #build the rsync command
        command = "rsync -avzh --log-file=#{log} #{source_folder} #{destination}"
        puts "Executing #{command}"
        #check if the command exit code was 0
        exit_code = system("#{command}")
        if !exit_code
            File.open("#{log}", 'a+') do |f|
                            f.write("#{Time.now} -- [ERROR] -- #{folder} -- rsync command failed: #{command} \n")
    #when the destination isn't there, log it
        puts "#{destination} doesn't exist!"
        #puts "Logfile written to #{log_folder}/#{vhost}.log"
        #write the log file (append or create if not there)
        File.open("#{log}", 'a+') do |f|
            f.write("#{Time.now} -- [ERROR] -- #{folder} -- Missing Plugin folder \n")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.