Parallel SVN update process - linux

I need to execute several SVN update processes in background under same folder structure as I have many subfolders and want to speed up whole thing.
I have folder structure like this:
/folder/subfolder1/
/folder/subfolder2/
/folder/subfolder3/
...
/folder/subfolder1000/
I'm trying to do something like this in bash script:
svn up /folder/subfolder1 &
svn up /folder/subfolder2 &
svn up /folder/subfolder3 &
Problem is in that SVN complains that '/folder' is locked and only first task finish correct, other two don't and got error message like this:
svn: Working copy '/folder' locked
svn: run 'svn cleanup' to remove locks (type 'svn help cleanup' for details)
Is there a way to accomplish task on this way with several parallel SVN process because doing one by one folder (selected by some other process) takes a lot time to finish?
P.S: I'm doing all this in higher programing language (PHP-CLI) but for simplicity of question I write it as bash script (got same problem).

In older versions of Subversion every subdirectory had its own .svn file. If your svn is old enough, and you run the commands in the subdirectories, then I think that won't lock the parent directory and the commands can succeed in parallel. Like this:
(cd /folder/subfolder1; svn up)&
(cd /folder/subfolder2; svn up)&
(cd /folder/subfolder3; svn up)&
Although, to be honest, I thought your original command should work too, I don't see why the parent directory gets locked.

Related

SVN Pre-commit Symbolic Link Path in Perl

In my workplace, there's one Perl script that runs on a Unix machine every time someone tries to check-in a file to the SVN repo for any of the 10-20 projects.
The way it works is that each project has its own "Hooks" folder with a file called "pre-commit" which SVN automatically executes when someone check-in something. Except the "pre-commit" file is actually a symbolic link to the one central Perl script common to all projects just so that if a change needs to be made to the Perl script it doesn't need to be done for every project.
So my problem is this: I need to put a text file in each of these projects' "hooks" directory, each one containing some settings specific to that project. So there will be 10-20 settings files (one per project) each in their respective "hooks" directory.
The problem is that I need to open these text files in the Perl script and read from them but I'm having issues letting Perl know where to find it. I tried using the $0 parameter which is supposed to tell me where the script is being executed from but because it's a symbolic link it just says "Not a directory" and the script terminates. I need to get the path of the "hooks" directory so that I can find the text file.
The SVN pre-commit script is supposed to be invoked with the path to the repository as its first argument. Inside a Perl script, that argument should be available as $ARGV[0]. You should be able to build the path to the corresponding hooks directory or to a file inside that directory by simply appending to the repository path, like this:
$repopath = $ARGV[0];
$hookspath = $repopath . "/hooks";
$myfilepath = $hookspath . "/myfile";
although for maximum portability it would be cleaner to use the pathname-manipulation functions in the File::Spec module to do this.
If this approach doesn't work then you'll have to explain more about how your Perl script gets invoked. For instance, if your pre-commit script is really a shell script wrapper that eventually invokes perl then perhaps it's not passing the pre-commit arguments along properly.
Showing us your current code that's failing would be a good thing too.

rsync not synchronizing .htaccess file

I am trying to rsync directory A of server1 with directory B of server2.
Sitting in the directory A of server1, I ran the following commands.
rsync -av * server2::sharename/B
but the interesting thing is, it synchronizes all files and directories except .htaccess or any hidden file in the directory A. Any hidden files within subdirectories get synchronized.
I also tried the following command:
rsync -av --include=".htaccess" * server2::sharename/B
but the results are the same.
Any ideas why hidden files of A directory are not getting synchronized and how to fix it. I am running as root user.
thanks
This is due to the fact that * is by default expanded to all files in the current working directory except the files whose name starts with a dot. Thus, rsync never receives these files as arguments.
You can pass . denoting current working directory to rsync:
rsync -av . server2::sharename/B
This way rsync will look for files to transfer in the current working directory as opposed to looking for them in what * expands to.
Alternatively, you can use the following command to make * expand to all files including those which start with a dot:
shopt -s dotglob
See also shopt manpage.
For anyone who's just trying to sync directories between servers (including all hidden files) -- e.g., syncing somedirA on source-server to somedirB on a destination server -- try this:
rsync -avz -e ssh --progress user#source-server:/somedirA/ somedirB/
Note the slashes at the end of both paths. Any other syntax may lead to unexpected results!
Also, for me its easiest to perform rsync commands from the destination server, because it's easier to make sure I've got proper write access (i.e., I might need to add sudo to the command above).
Probably goes without saying, but obviously your remote user also needs read access to somedirA on your source server. :)
I had the same issue.
For me when I did the following command the hidden files did not get rsync'ed
rsync -av /home/user1 server02:/home/user1
But when I added the slashes at the end of the paths, the hidden files were rsync'ed.
rsync -av /home/user1/ server02:/home/user1/
Note the slashes at the end of the paths, as Brian Lacy said the slashes are the key. I don't have the reputation to comment on his post or I would have done that.
I think the problem is due to shell wildcard expansion. Use . instead of star.
Consider the following example directory content
$ ls -a .
. .. .htaccess a.html z.js
The shell's wildcard expansion translates the argument list that the rsync program gets from
-av * server2::sharename/B
into
-av a.html z.js server2::sharename/B
before the command starts getting executed.
The * tell to rsynch to not synch hidden files. You should not omit it.
On a related note, in case any are coming in from google etc trying to find while rsync is not copying hidden subfolders, I found one additional reason why this can happen and figured I'd pay it forward for the next guy running into the same thing: if you are using the -C option (obviously the --exclude would do it too but I figure that one's a bit easier to spot).
In my case, I had a script that was copying several folders across computers, including a directory with several git projects and I noticed that the I couldn't run any of the normal git commands in the copied repos (yes, normally one should use git clone but this was part of a larger backup that included other things). After looking at the script, I found that it was calling rsync with 7 or 8 options.
After googling didn't turn up any obvious answers, I started going through the switches one by one. After dropping the -C option, it worked correctly. In the case of the script, the -C flag appears to have been added as a mistake, likely because sftp was originally used and -C is a compression-related option under that tool.
per man rsync, the option is described as
--cvs-exclude, -C auto-ignore files in the same way CVS does
Since CVS is an older version control system, and given the man page description, it makes perfect sense that it would behave this way.

Local Git as autosave

I would like a local GIT is my home directory to implement autosave to the repository that happens every five minutes.
I have two Questions:
Is this s sane thing to do?
How does one go about writing a script that implements this functionality for a specified set of directories in the home directory on linux?
The aim is to capture all the histories all the important files in my home directory automatically without any input from me. I can use this whenever I screw-up.
Sanity is all relative!
I guess it depends on why you are backing up. If it's for hardware failure, then this won't work because the repository is in the same folder (/home/) so if the folder goes, the repo goes. Unless of course you are pushing it to a storage repo on another machine somewhere as the actual backup.
We do use git to store important things, especially research papers and PDF's, so we can easily share them.
You would write a cron job that runs a script every so often. Basically you would write a simple bash script that does a git commit -a -m "commit message" periodically in your folder. The tricky part is doing the git add on the new files that were created so they are tracked. You will likely need to do a git status and parse the output from it in your script to find the new files, then git add that list. Python may be the easiest way to do that. Then you register that with cron.
Google is your friend here, there are plenty of examples on how to register scripts with cron.
Write a shell script that would enter each directory you want and run
git add .
git commit -m "new change"
git push
and then use cron to run the script each 5 minutes.
Write a shell script to do the following
1) git status --u=no //It gives you the files which are modified
2) Iterate through the file list from step 1 and do git add <file>
3) git commit -m "latest change <date:time>"
Schedule this script in cron.

Nightly backup and merging backup

I have a nightly back up script that makes a backup from one server of any files that have been modified and thensync them across to our back server.
/var/backups/backup-2011-04-02/backuped/ backuped files and folders
The format above is the nightly incremental backup, which copies all the files and folders to a date stamped folder and then another folder underneath.
Thinking of a script which would run after the back up script to merge all the files in the /var/backups/backup-2011-04-02/backuped/ into /var/www/live/documents
So in theory I need to merge a number of different folders from the backup into the live www on the backup server only with the right date
So whats the best way to go about this script?
You could run rsync on each backup directory to the destination in order of
creation:
$ for f in `ls -t /var/backups`; do rsync -aL "/var/backups/$f" /var/www/live/documents/; done
Of course you can put this line in a nightly cron job. The only thing to look out for is the line above will choke if the filenames in your backup directory have spaces in them, but it looks like they don't, so you may be ok.

Keep Remote Directory Up-to-date

I absolutely love the Keep Remote Directory Up-to-date feature in Winscp. Unfortunately, I can't find anything as simple to use in OS X or Linux. I know the same thing can theoretically be accomplished using changedfiles or rsync, but I've always found the tutorials for both tools to be lacking and/or contradictory.
I basically just need a tool that works in OSX or Linux and keeps a remote directory in sync (mirrored) with a local directory while I make changes to the local directory.
Update
Looking through the solutions, I see a couple which solve the general problem of keeping a remote directory in sync with a local directory manually. I know that I can set a cron task to run rsync every minute, and this should be fairly close to real time.
This is not the exact solution I was looking for as winscp does this and more: it detects file changes in a directory (while I work on them) and then automatically pushes the changes to the remote server. I know this is not the best solution (no code repository), but it allows me to very quickly test code on a server while I develop it. Does anyone know how to combine rsync with any other commands to get this functionality?
lsyncd seems to be the perfect solution. it combines inotify (kernel builtin function which watches for file changes in a directory trees) and rsync (cross platform file-syncing-tool).
lsyncd -rsyncssh /home remotehost.org backup-home/
Quote from github:
Lsyncd watches a local directory trees event monitor interface (inotify or fsevents). It aggregates and combines events for a few seconds and then spawns one (or more) process(es) to synchronize the changes. By default this is rsync. Lsyncd is thus a light-weight live mirror solution that is comparatively easy to install not requiring new filesystems or blockdevices and does not hamper local filesystem performance.
How "real-time" do you want the syncing? I would still lean toward rsync since you know it is going to be fully supported on both platforms (Windows, too, with cygwin) and you can run it via a cron job. I have a super-simple bash file that I run on my system (this does not remove old files):
#!/bin/sh
rsync -avrz --progress --exclude-from .rsync_exclude_remote . remote_login#remote_computer:remote_dir
# options
# -a archive
# -v verbose
# -r recursive
# -z compress
Your best bet is to set it up and try it out. The -n (--dry-run) option is your friend!
Keep in mind that rsync (at least in cygwin) does not support unicode file names (as of 16 Aug 2008).
What you want to do for linux remote access is use 'sshfs' - the SSH File System.
# sshfs username#host:path/to/directory local_dir
Then treat it like an network mount, which it is...
A bit more detail, like how to set it up so you can do this as a regular user, on my blog
If you want the asynchronous behavior of winSCP, you'll want to use rsync combined with something that executes it periodically. The cron solution above works, but may be overkill for the winscp use case.
The following command will execute rsync every 5 seconds to push content to the remote host. You can adjust the sleep time as needed to reduce server load.
# while true; do rsync -avrz localdir user#host:path; sleep 5; done
If you have a very large directory structure and need to reduce the overhead of the polling, you can use 'find':
# touch -d 01/01/1970 last; while true; do if [ "`find localdir -newer last -print -quit`" ]; then touch last; rsync -avrz localdir user#host:path; else echo -ne .; fi; sleep 5; done
And I said cron may be overkill? But at least this is all just done from the command line, and can be stopped via a ctrl-C.
kb
To detect changed files, you could try fam (file alteration monitor) or inotify. The latter is linux-specific, fam has a bsd port which might work on OS X. Both have userspace tools that could be used in a script together with rsync.
I have the same issue. I loved winscp "keep remote directory up to date" command. However, in my quest to rid myself of Windows, I lost winscp. I did write a script that uses fileschanged and rsync to do something similar much closer to real time.
How to use:
Make sure you have fileschanged installed
Save this script in /usr/local/bin/livesync or somewhere reachable in your $PATH and make it executable
Use Nautilus to connect to the remote host (sftp or ftp)
Run this script by doing livesync SOURCE DEST
The DEST directory will be in /home/[username]/.gvfs/[path to ftp scp or whatever]
A Couple downsides:
It is slower than winscp (my guess is because it goes through Nautilus and has to detect changes through rsync as well)
You have to manually create the destination directory if it doesn't already exist. So if you're adding a directory, it won't detect and create the directory on the DEST side.
Probably more that I haven't noticed yet
Also, do not attempt to synchronize a SRC directory named "rsyncThis". That will probably not be good :)
#!/bin/sh
upload_files()
{
if [ "$HOMEDIR" = "." ]
then
HOMEDIR=`pwd`
fi
while read input
do
SYNCFILE=${input#$HOMEDIR}
echo -n "Sync File: $SYNCFILE..."
rsync -Cvz --temp-dir="$REMOTEDIR" "$HOMEDIR/$SYNCFILE" "$REMOTEDIR/$SYNCFILE" > /dev/null
echo "Done."
done
}
help()
{
echo "Live rsync copy from one directory to another. This will overwrite the existing files on DEST."
echo "Usage: $0 SOURCE DEST"
}
case "$1" in
rsyncThis)
HOMEDIR=$2
REMOTEDIR=$3
echo "HOMEDIR=$HOMEDIR"
echo "REMOTEDIR=$REMOTEDIR"
upload_files
;;
help)
help
;;
*)
if [ -n "$1" ] && [ -n "$2" ]
then
fileschanged -r "$1" | "$0" rsyncThis "$1" "$2"
else
help
fi
;;
esac
You could always use version control, like SVN, so all you have to do is have the server run svn up on a folder every night. This runs into security issues if you are sharing your files publicly, but it works.
If you are using Linux though, learn to use rsync. It's really not that difficult as you can test every command with -n. Go through the man page, the basic format you will want is
rsync [OPTION...] SRC... [USER#]HOST:DEST
the command I run from my school server to my home backup machine is this
rsync -avi --delete ~ me#homeserv:~/School/ >> BackupLog.txt
This takes all of the files in my home directory (~) and uses rsync's archive mode (-a), verbosly (-v), lists all of the changes made (-i), while deleting any files that don't exist anymore (--delete) and puts the in the Folder /home/me/School/ on my remote server. All of the information it prints out (what was copied, what was deleted, etc.) is also appended to the file BackupLog.txt
I know that's a whirlwind tour of rsync, but I hope it helps.
The rsync solutions are really good, especially if you're only pushing changes one way. Another great tool is unison -- it attempts to syncronize changes in both directions. Read more at the Unison homepage.
Great question I have searched answer for hours !
I have tested lsyncd and the problem is that the default delay is far too long and no example command line give the -delay option.
Other problem is that by default rsync ask password each time !
Solution with lsyncd :
lsyncd --nodaemon -rsyncssh local_dir remote_user#remote_host remote_dir -delay .2
other way is to use inotify-wait in a script :
while inotifywait -r -e modify,create,delete local_dir ; do
# if you need you can add wait here
rsync -avz local_dir remote_user#remote_host:remote_dir
done
For this second solution you will have to install inotify-tools package
To suppress the need to enter password at each change, simply use ssh-keygen :
https://superuser.com/a/555800/510714
It seems like perhaps you're solving the wrong problem. If you're trying to edit files on a remote computer then you might try using something like the ftp plugin for jedit. http://plugins.jedit.org/plugins/?FTP This ensures that you have only one version of the file so it can't ever be out of sync.
Building off of icco's suggestion of SVN, I'd actually suggest that if you are using subversion or similar for source control (and if you aren't, you should probably start) you can keep the production environment up to date by putting the command to update the repository into the post-commit hook.
There are a lot of variables in how you'd want to do that, but what I've seen work is have the development or live site be a working copy and then have the post-commit use an ssh key with a forced command to log into the remote site and trigger an svn up on the working copy. Alternatively in the post-commit hook you could trigger an svn export on the remote machine, or a local (to the svn repository) svn export and then an rsync to the remote machine.
I would be worried about things that detect changes and push them, and I'd even be worried about things that ran every minute, just because of race conditions. How do you know it's not going to transfer the file at the very same instant it's being written to? Stumble across that once or twice and you'll lose all of the time-saving advantage you had by constantly rsyncing or similar.
Will DropBox (http://www.getdropbox.com/) do what you want?
User watcher.py and rsync to automate this. Read the following step by step instructions here:
http://kushellig.de/linux-file-auto-sync-directories/
I used to have the same setup under Windows as you, that is a local filetree (versioned) and a test environment on a remote server, which I kept mirrored in realtime with WinSCP. When I switched to Mac I had to do quite some digging before I was happy, but finally ended up using:
SmartSVN as my subversion client
Sublime Text 2 as my editor (already used it on Windows)
SFTP-plugin to ST2 which handles the uploading on save (sorry, can't post more than 2 links)
I can really recommend this setup, hope it helps!
I have been using WinSCP on Wine for a few years now and it works fine for the syncing operations you mention.
Here are some instructions I posted to Github on how to setup via wine: WinSCP_On_Wine
Just be aware that WinSCP is not being actively tested on wine so there may be some quirky issues. however, I use it daily on Ubuntu 20.04 for all my devops and have never lost a file and rarely experience any of such quirks.
You can also use Fetch as an SFTP client, and then edit files directly on the server from within that. There are also SSHFS (mount an ssh folder as a Volume) options. This is in line with what stimms said - are you sure you want stuff kept in sync, or just want to edit files on the server?
OS X has it's own file notifications system - this is what Spotlight is based upon. I haven't heard of any program that uses this to then keep things in sync, but it's certainly conceivable.
I personally use RCS for this type of thing:- whilst it's got a manual aspect, it's unlikely I want to push something to even the test server from my dev machine without testing it first. And if I am working on a development server, then I use one of the options given above.
Well, I had the same kind of problem and it is possible using these together: rsync, SSH Passwordless Login, Watchdog (a Python sync utility) and Terminal Notifier (an OS X notification utility made with Ruby. Not needed, but helps to know when the sync has finished).
I created the key to Passwordless Login using this tutorial from Dreamhost wiki: http://cl.ly/MIw5
1.1. When you finish, test if everything is ok… if you can't Passwordless Login, maybe you have to try afp mount. Dreamhost (where my site is) does not allow afp mount, but allows Passwordless Login. In terminal, type:
ssh username#host.com
You should login without passwords being asked :P
I installed the Terminal Notifier from the Github page: http://cl.ly/MJ5x
2.1. I used the Gem installer command. In Terminal, type:
gem install terminal-notifier
2.3. Test if the notification works.In Terminal, type:
terminal-notifier -message "Starting sync"
Create a sh script to test the rsync + notification. Save it anywhere you like, with the name you like. In this example, I'll call it ~/Scripts/sync.sh I used the ".sh extension, but I don't know if its needed.
#!/bin/bash
terminal-notifier -message "Starting sync"
rsync -azP ~/Sites/folder/ user#host.com:site_folder/
terminal-notifier -message "Sync has finished"
3.1. Remember to give execution permission to this sh script. In Terminal, type:
sudo chmod 777 ~/Scripts/sync.sh
3.2. Run the script and verify if the messages are displayed correctly and the rsync actually sync your local folder with the remote folder.
Finally, I downloaded and installed Watchdog from the Github page: http://cl.ly/MJfb
4.1. First, I installed the libyaml dependency using Brew (there are lot's of help how to install Brew - like an "aptitude" for OS X). In Terminal, type:
brew install libyaml
4.2. Then, I used the "easy_install command". Go the folder of Watchdog, and type in Terminal:
easy_install watchdog
Now, everything is installed! Go the folder you want to be synced, change this code to your needs, and type in Terminal:
watchmedo shell-command
--patterns="*.php;*.txt;*.js;*.css" \
--recursive \
--command='~/Scripts/Sync.sh' \
.
It has to be EXACTLY this way, with the slashes and line breaks, so you'll have to copy these lines to a text editor, change the script, paste in terminal and press return.
I tried without the line breaks, and it doesn't work!
In my Mac, I always get an error, but it doesn't seem to affect anything:
/Library/Python/2.7/site-packages/argh-0.22.0-py2.7.egg/argh/completion.py:84: UserWarning: Bash completion not available. Install argcomplete.
Now, made some changes in a file inside the folder, and watch the magic!
I'm using this little Ruby-Script:
#!/usr/bin/env ruby
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Rsyncs 2Folders
#
# watchAndSync by Mike Mitterer, 2014 <http://www.MikeMitterer.at>
# with credit to Brett Terpstra <http://brettterpstra.com>
# and Carlo Zottmann <https://github.com/carlo/haml-sass-file-watcher>
# Found link on: http://brettterpstra.com/2011/03/07/watch-for-file-changes-and-refresh-your-browser-automatically/
#
trap("SIGINT") { exit }
if ARGV.length < 2
puts "Usage: #{$0} watch_folder sync_folder"
puts "Example: #{$0} web keepInSync"
exit
end
dev_extension = 'dev'
filetypes = ['css','html','htm','less','js', 'dart']
watch_folder = ARGV[0]
sync_folder = ARGV[1]
puts "Watching #{watch_folder} and subfolders for changes in project files..."
puts "Syncing with #{sync_folder}..."
while true do
files = []
filetypes.each {|type|
files += Dir.glob( File.join( watch_folder, "**", "*.#{type}" ) )
}
new_hash = files.collect {|f| [ f, File.stat(f).mtime.to_i ] }
hash ||= new_hash
diff_hash = new_hash - hash
unless diff_hash.empty?
hash = new_hash
diff_hash.each do |df|
puts "Detected change in #{df[0]}, syncing..."
system("rsync -avzh #{watch_folder} #{sync_folder}")
end
end
sleep 1
end
Adapt it for your needs!
If you are developing python on remote server, Pycharm may be a good choice to you. You can synchronize your remote files with your local files utilizing pycharm remote development feature. The guide link as:
https://www.jetbrains.com/help/pycharm/creating-a-remote-server-configuration.html

Resources