When I try to execute the SQL Server 2012 BCP.exe
utility to dump the contents of a table to a file using a fully qualified path to the exe,
D:\SQL2012\110\Tools\Binn\bcp.exe
DBNAME.DBO.TABLENAME OUT %FileServerProject%\IMPLEMENTATION\DAT\Pre_Run_BaseTables\CDB_ACCT_CURR.DAT -S%SqlServer% -T -N >> %LogFolder%\Log.log
...I get an ACCESS DENIED error.
However, when I remove the fully qualified path to the exe and run,
bcp.exe
DBNAME.DBO.TABLENAME OUT %FileServerProject%\IMPLEMENTATION\DAT\Pre_Run_BaseTables\CDB_ACCT_CURR.DAT -S%SqlServer% -T -N >> %LogFolder%\Log.log
It works fine.
If the path isn't qualified, my understanding is that Windows will search each folder specified in the PATH
environmental variable looking for the specified exe, and execute first one found. So, I executed the following command from the console to see my PATH
variable.
ECHO %PATH%
Cleaning up the miscellaneous unrelated paths from the output, I saw the following SQL-related folder returned in this order:
D:\SQL2012\110\DTS\Binn\;
D:\SQL2012 (86)\110\Tools\Binn\;
D:\SQL2012\110\Tools\Binn\;
The latter Tools\Binn
path was the only folder that contained the bcp.exe
utility.
My question is this:
Since the same EXE was executed whether I explicitly qualified the path or left Windows to find it by searching the path variable, why did I get an ACCESS DENIED error when I ran using the fully qualified path and not when I did not qualify the path?
Note that in both cases I was running under an ID that had read and execute rights to the TOOLS\BINN
folder. In the case where I was using the fully qualified path, if I added the account to the Local group, it would work but this was not a viable solution. Also, the ID had LogOn As Batch
rights to the server.
Update:
I now have no doubt that when I execute using the unqualified bcp.exe
path that I am in fact running the only copy of bcp.exe
on the server. For starters, I used Search Everything to extensively search every drive on the server. I found three occurrences. I then renamed the 2 that I did not want to accidentally reference.
I then reran the job using the unqualified bcp.exe
path and using Task Manager's process tab, I found bcp.exe
running under the service account. I then right-clicked on the file name and selected the context menu "Open File Location", and it took me to the only location of the bcp.exe
file that was not renamed -- the file that I was intentionally trying to target with the fully qualified name.
D:\SQL2012\110\Tools\Binn
Since the bcp.exe was not qualified, it ran successfully.
Update 2 So far, 42 people have looked at this. I'd be curious if people are looking at this saying "that's impossible, that the facts of this case must not be exactly as I've stated."
Almost there: I simplified the batch file down to the bare minimum to reproduce the problem. You will notice that I changed our true path names, but I kept the gist of it.
Here's the "Before" code:
----------------------------------------------------------------
Output of messages for workload object TESTDUMP/GHG9999I.11/MAIN
Start date Fri Sep 25 13:33:36 2015
----------------------------------------------------------------
C:\Users\MyServiceAccount>WHERE bcp.exe
INFO: Could not find files for the given pattern(s).
C:\Users\MyServiceAccount> D:\SQL2012\110\Tools\Binn\bcp.exe MyDB.DBO.MyTable OUT \\MyFileServer\IMData\MyDB_SOURCE\IMPLEMENTATION\DAT\Pre_Run_BaseTables\MyTable.DAT -S MyDbServer\int -T -N 1>>\\MyFileServer\IMData\MyDB_SOURCE\Logs\MyTable_BCP_out.log
Access is denied.
C:\Users\MYSERVICEACCOUNT>ECHO RESULT=1
RESULT=1
Here's the "After,", which worked
----------------------------------------------------------------
Output of messages for workload object TESTDUMP/GHG9999I.10/MAIN
Start date Fri Sep 25 13:33:00 2015
----------------------------------------------------------------
C:\Users\MyServiceAccount>WHERE bcp.exe
INFO: Could not find files for the given pattern(s).
C:\Users\MyServiceAccount>"D:\SQL2012\110\Tools\Binn\bcp.exe" MyDB.DBO.MyTable OUT \\MyFileServer\IMData\MyDB_SOURCE\IMPLEMENTATION\DAT\Pre_Run_BaseTables\MyTable.DAT -S MyDbServer\int -T -N 1>>\\MyFileServer\IMData\MyDB_SOURCE\Logs\MyTable_BCP_out.log
C:\Users\MYSERVICEACCOUNT>ECHO RESULT=0
RESULT=0
Note that the difference is that the BCP path that worked was enclosed in quotes. I would have thought that this would have been important only if the path contained embedded spaces. I am confused why it mattered in this case.
A secondary new concern is why the WHERE
command failed to work when running under MYSERVICDEACCOUNT
through a scheduler. The command works when I log in manually under MYLANID
, navigate to c:\users\mylanid
, and try it.
If someone can explain why the quotes mattered, they get 100 pts and my gratitude.
Update 4:
I located the AgentParm.txt file on a server where the same code works. It was under the Program Files folder:
# Agent settings for nt-x86-64
agentname=MyWorkingServer
log.archive=2
oscomponent.jvm=server
On the server that we have been discussing where I have the issue when the batch file is unquoted, I see the following in the Program Files (x86) folder. All other lines were the same, so I excluded them. I did not see any mentioned of oscomponent.cmdprefix.force.quotes.full.
# Agent settings for nt-x86-32
agentname=MyServer
Do I need the 64 bit version of CA scheduler to run 64 bit exes? If so, will I have an issue running 32 bit exes (like SQL Server dtexec.exe) with the 64 bit CW Scheduler?
where bcp
should show you the path to the instance that will run if you don't specify a path. (Note that the process running under the service account can't be the process you launched on the command line - not unless you're logged in as the service account.) Note also that it is possible for an application to behave differently depending on the command line used to launch it, but it is unusual. – Pinafore%LogFolder%
) is a relative path and when you runbcp.exe
with no path, it's appended to the current directory and when run with fully qualified path its appended to a directory where the task doesn't have access. Pure guesswork, but if it turns out correct - I'll write it up as an answer... :) – Irretrievable%FileServerProject%
and%SqlServer%
(don't need exact values if confidential - just representative)? The full error message would help - is itSQL Server does not exist or access denied.
? I'm assuming it's that, rather than the log file that has access denies? – Irretrievable\` character. Maybe it needs to be
\\\` if it's not quoted. Although if that was the case, it's strange that it doesn't also affect the paths passed in as arguments to the job. – Irretrievablecmd
orpowershell
environments with exactly the same directory names. I don't have CA automation or SQL server to test the exact same configurations. My last roll of the dice is that CA is doing something to the path in translation when it is not quoted - possibly the\110
is problematic and being treated as some kind of escape code (which would be a bug). I don't think I can add anything further – Irretrievable