Redirecting Errors to a File in Windows Batch Scripts

In my post on Redirecting Output to a File in Windows Batch Scripts, I discussed the basics of output redirection into a text file and how this can be used for logging, including error logging by using the >& operator to combine the stderr and stdout streams. But Mark asked, “How do you just pipe stderr without joining it to stdout?” Good question!

So normal output redirection is handled with just the > or >> operators (depending on whether you want to overwrite or append the target file), like so:

dir >> myfile.txt

The operator outputs the stdout stream by default. But it can be modified to output the stderr stream by just specifying that stream with the operator. Remember, stderr is stream 2. So, you would do like so:

dir 2>> myfile.txt

This would write only the error output to the file.

Why That Batch For Loop Isn’t Working

Time for another fun foray into Windows batch scripts. Perhaps you've used the FOR /F command to loop through the contents of a file (for instance, perhaps some data that was redirected to a text file from a command). Grab a line, act on its values, and output some text and commands.

Let's set this up. First, we have a data file named SomeAccounts.txt:

Josh
Mary
Suzy
Amanda
Trisha
Ben

Then, we have ProcessAccounts.bat, which we want to just loop through the accounts in the text file, tell us what they are, and tell us the first letter of the account name (just to have something to do):

DOS:
  1. set file=SomeAccounts.txt
  2. FOR /F %%i IN (%file%) DO (
  3. set username=%%i
  4. echo My account, %username%, starts with %username:~0,1%.
  5. )

Except when you do this, you encounter a problem: All of the values from the FOR loop are the same! It's as if the for loop ran the proper number of times, but it just ran on the last record over and over again! See below:

My account, Ben, starts with B.
My account, Ben, starts with B.
My account, Ben, starts with B.
My account, Ben, starts with B.
My account, Ben, starts with B.
My account, Ben, starts with B.

What's actually happening is the FOR loop is indeed running over every line, and setting the variables as instructed, but the results of those variables being altered isn't echoed until the FOR loop is complete, so the last value of the variable is what displays. This wouldn't be a problem if you were just using your FOR parameter, in this case %%i, but any variables you set while in the FOR loop, like username, experience this "wait until you're out of the loop" phenomenon.

The fix is simple enough, if you know about it! But I've found the solution to be a bit elusive, which is the whole point of sharing it now.

The key is the setlocal EnableDelayedExpansion command. As explained at ss64.com, making this statement before your FOR loop will enable you to display variables as their value at the moment you're referencing them, or their "intermediate values" while in the middle of the FOR loop. In addition to calling the setlocal command, you then have to reference your variables with the exclamation point (!) rather than percent (%) to indicate that you want to use the intermediate value.

Your script will then look like this:

DOS:
  1. setlocal EnableDelayedExpansion
  2. set file=SomeAccounts.txt
  3. FOR /F %%i IN (%file%) DO (
  4. set username=%%i
  5. echo My account, !username!, starts with !username:~0,1!.
  6. )

It will now happily act as desired, outputting these results:

My account, Josh, starts with J.
My account, Mary, starts with M.
My account, Suzy, starts with S.
My account, Amanda, starts with A.
My account, Trisha, starts with T.
My account, Ben, starts with B.

Upgrading Subversion Requires a Bindings Update for Trac!

My Subversion/Trac server was at Trac v0.9.6 and Subversion v1.3.x because those were the latest stable releases when I set up the server. I decided it would be relatively quick and painless to at least get the latest version of Subversion (v1.4.5) installed since I didn't see anything on the web about Trac v0.9.6 being incompatible with newer Subversion builds.

Using the Windows binary installer, I had no problem installing Subversion v1.4.5 on the server. I tested everything and Subversion still worked, it showed the new version when accessing via web access, and Trac still worked fine.

Alas: Don't forget that an upgraded version of Subversion will not upgrade your repository. It will upgrade a working copy of a checked-out repository, but it will not upgrade the repository itself.

That said, I was unaware of one more step that you must take to upgrade Subversion on a Subversion/Trac setup: You must also upgrade the Python bindings to Subversion.

This became apparent the next time I created a new repository, which was not a v1.4.x repository, and when I tried to build a Trac environment to point to it, Trac got upset because of the classic "Expected version '3' of repository; found version '5'" error. To fix this, you must set up new bindings to the new version of Subversion, as explained in the TracSubversion page.

Now, I obviously love Subversion and I love Trac, but honestly, straight-forward documentation that is easy to understand for someone who doesn't want to get in the thick of it isn't really the strong suit for these communities, at least when it comes to installation and deployment on the server. What exactly it means--and how to do it--when they say, "Update the Subversion bindings" is not easy to understand. However, the solution is simple. All that is needed is to download the appropriate "svn-python" Windows installer that matches your version of Subversion and Python (in my case, 1.4.5 and py2.3) and run it on the server.

In my case, I had to stop Apache for the installation to succeed. Upon restarting Apache, everything worked great.

Windows Vista and Samba Not Getting Along: NTLMv2 is the Culprit

After installing Windows Vista, I could not connect to my Samba fileshares. I'm running Samba v3.0.10 on CentOS v4.4.

It turns out that NTLMv2, the authentication protocol, is required by default on Windows Vista. According to the Samba Features by Release wiki page, support for NTLMv2 in Samba wasn't fully developed until Samba v3.0.21.

Running yum would be a quick way to upgrade Samba to a more recent release. For some reason, though, the repositories I'm pointing to only have v3.0.10 as the latest available update. Rather than hassling with it, I found an article that attacks the issue from the Vista end.

The article Get Vista and Samba to Work explains how to get Vista to use the older authentication protocols, like the original NTLM. After making this change, I was able to login to my shares immediately.

Basically, all you need to do is run the Local Security Policies console snapin (secpol.msc), open Local Policies --> Security Options --> Network Security: LAN Manager authentication level, and change the setting from "NTLMv2 responses only" to one of the more lenient settings, like "LM and NTLM – use NTLMV2 session security if negotiated".

This works for me because I have one, sometimes two, machines with Windows Vista connecting to my server. If you had lots of machines connecting to the server, it'd obviously be worth your time to just upgrade Samba to a version that supports NTLMv2.

  Theme Brought to you by Directory Journal and Elegant Directory.