Executing exe file in xp_cmdshell doesn't work - sql-server

I have created a user in SQL Server with:
CREATE LOGIN adminuser WITH PASSWORD = 'ABCDegf123';
GO
EXEC master..sp_addsrvrolemember #loginame = N'adminuser', #rolename = N'sysadmin'
GO
Then I connected with this user.
What I want to do, is trigger this ftp command:
ftp -s:C:\Users\sss\Documents\script_ftp\ftp.txt
So I created a trigger:
CREATE TRIGGER sss14
ON Table_1
AFTER INSERT
AS
DECLARE #CMDSQL VARCHAR(1000)
SET #CMDSQL = 'ftp -s:C:\Users\sss\Documents\script_ftp\ftp.txt'
EXEC master..xp_cmdshell #CMDSQL
However, this doesn't work.
Note that creating a folder with xp_cmdshell works correctly. and when I run 'code' it's launch visual studio code as background process

When xp_cmdshell is called, SQL Server does not care about the output and does not consider any failure.
However, you can insert the output to temp table and see the result. Please run below in SSMS to check.
DECLARE #CMDSQL VARCHAR(1000)
SET #CMDSQL = 'ftp -s:C:\Users\sss\Documents\script_ftp\ftp.txt'
create table #output(output varchar(2000))
insert into #output
Exec master..xp_cmdshell #CMDSQL
select * from #output
drop table #output
The command run with xp_cmdshell use SQL Server service account to run OS commands. Please check if SQL Server service account has got permission to perform ftp. If not, grant the appropriate permission.

Related

How do I look at SQL Agent Job without starting SQL Agent?

I have just set up a new SQL Server instance on a new server and moved our application to use the new server. So I've had to turn SQL Agent off on the old server - turning it on would start the scheduler and start sending out emails and running things that shouldn't be run any more.
However, I need to take a close look at a SQL Agent Job on the old server, and ideally reverse-engineer the code to recreate it so I can modify it and apply it to the new server.
How do I generate the code for that Job on the old server without turning SQL Agent on?
Thanks
Even if SQL server agent is not running, you can see how jobs and schedules were set up by viewing the following system DMVs.
msdb.dbo.sysjobs_view
msdb.dbo.sysjobs
msdb.dbo.sysjobschedules
msdb.dbo.sysschedules
I use preset scripts to create all my jobs and schedules independent of the server. Here is a sample script to create the recycle log job. You can modify this or use any piece of this as you see fit.
DECLARE #sql nvarchar(max)
BEGIN TRY
IF EXISTS (SELECT job_id
FROM msdb.dbo.sysjobs_view
WHERE name = N'Cycle SQL log')
EXEC msdb.dbo.sp_delete_job #job_name=N'Cycle SQL log'
, #delete_unused_schedule=1
EXEC msdb.dbo.sp_add_job
#job_name = N'Cycle SQL log',
#description = N'This job forces SQL to start a new error log (In the Managment node of SSMS)',
#owner_login_name = N'your_sql_login' ;
EXEC msdb.dbo.sp_add_jobstep
#job_name = N'Cycle SQL log',
#step_name = N'sp_cycle_errorlog',
#subsystem = N'TSQL',
#command = N'exec sp_cycle_errorlog' --put your executable code here
--These next two lines set the target server to local, so that the job can be modified if necessary
SET #sql = 'EXEC msdb.dbo.sp_add_jobserver #job_name=N''Cycle SQL Log'', #server_name = N''' + ##SERVERNAME + ''''
EXEC sys.sp_executesql #stmt = #sql
END TRY
BEGIN CATCH
PRINT 'Uh-oh. Something bad happened when creating the Cycle SQL Log job. See the following error.'
PRINT CAST(ERROR_MESSAGE() AS NVARCHAR(1000))
END CATCH
You can use use code to automate the addition of schedules based on values you pull from the DMVs listed above.

Programmatically give access to databases

Scenario: Instructor of a database course wants to do the following for each of 100 students every semester: (a) create login from windows, (b) create database for each student where they are db_owner, (c) each student has read access to a database.
Here is the script I have so far:
DECLARE #DBname varchar(10) = 'aa1833'
DECLARE #Lname varchar(20) = 'STUDENTS'+'\'+#DBname
DECLARE #CreateDB varchar(max) = 'CREATE DATABASE '+#DBname
EXEC(#CreateDB)
DECLARE #CreateLogin varchar(max) = 'CREATE LOGIN ['+#Lname+ '] FROM WINDOWS'
EXEC(#CreateLogin)
USE sample_database
EXEC sp_addrolemember 'db_datareader', #Lname
EXEC sp_droprolemember 'db_owner', #Lname
DECLARE #dbRights varchar(max) = 'USE '+#DBname
EXEC(#dbRights)
EXEC sp_addrolemember 'db_owner', #Lname
I would appreciate help with following issues:
The above script is able to create logins and user's database. However, access rights (to individual database and sample database) are incorrect.
To manage server space, I would like to delete student accounts and their databases at the end of each semester. Can we have database names such as students\f21\001\aa1833?
Any other comments to improve this set up (students cannot access others' work and edit contents) would be appreciated.
SQL Server 15
The database context reverts back to the outer context (sample_database) after the dynamic SQL USE statement runs so the subsequent sp_addrolemember runs in sample_database instead of aa1833 as intended.
Execute USE and sp_addrolemember in the same dynamic SQL batch to avoid the issue:
DECLARE #dbRights varchar(max) = 'USE ' + QUOTENAME(#DBname) + N';EXEC sp_addrolemember ''db_owner'', #Lname';
sp_executesql #dbRights, N'#Lname sysname', #Lname = #Lname;

Using bcp utility from within a stored procedure to output records to a text file

I have been using the bcp utility from the command line to save the result of a query to a text file e.g.
C:> bcp "SELECT Name FROM [DatabaseName].[dbo].[Employees]" queryout "filepath.txt" -c -T
I am currently trying to find away to execute this and similar bcp commands from a stored procedure.
Research for solution
Investigated xp_cmdshell stored procedure (Disabled for security reasons)
Use SQL Server agent and use job steps to invoke the command shell
Post from mssqltips
.
Attempt at a solution (Code below lies within stored procedure)
DECLARE #job NVARCHAR(100)
SET #job ='execute_bcp'
EXEC msdb..sp_add_job #job_name = #job,
#description = 'Execute bcp command',
#owner_login_name = 'sa',
#delete_level = 1
EXEC msdb..sp_add_jobstep #job_name = #job,
#step_id = 1,
#step_name ='Command Shell Execution', #subsystem = 'CMDEXEC',
#command = 'bcp "SELECT Name FROM [DatabaseName].[dbo].[Employees]" queryout "filepath.txt" -c -T',
#on_success_action =1
EXEC msdb..sp_add_jobserver #job_name =#job
EXEC msdb..sp_start_job #job_name = #job
The outcome of running this stored procedure is
'execute_bcp' has started.
However, when I check the file path location specified above the file has not been created.
Thanks in advance for any help and advice.

SQL Server 2012 -- xp_fileexist returns 0 when checking for file on local machine

The SQL server exists on the same machine I am physically logged into, and xp_fileexist is failing to recognize any files on the D drive, which is not a network drive. I already configured xp_cmdshell and restarted the SQL server instance. Any other ideas?
Yup, we had the same problem. On SQL Server 2008, our legacy xp_fileexist code worked fine, but on SQL Server 2012... nope.
It would work if we ran the xp_fileexist command as ourselves (with Admin rights) but not when we ran it as a SQL Server user, who didn't exist as an Active Directory user. Even if we changed the security on that folder to give Everyone full permissions, the xp_fileexist would fail, always returning a 0, as if a file within that folder didn't exist.
However, what did work was to use dir from within a Stored Procedure, and test if the file existed that way. (Yeah, I know... I'm rolling my eyes myself... this is dodgy..)
Here's the Stored Procedure I wrote, based on suggestions on this site :
CREATE PROCEDURE [dbo].[DoesFileExist]
(
#directoryName NVARCHAR(500),
#filename NVARCHAR(500)
)
AS
BEGIN
-- Does a file exist in a particular folder ?
--
-- EXEC [dbo].[DoesFileExist] 'D:\MyFiles', 'SomeExcelFile.xls'
--
DECLARE #bFileExists INT
DECLARE #cmd nvarchar(300);
SELECT #cmd = 'dir ' + #directoryName + '\' + #filename;
DECLARE #dir TABLE ([output] varchar( 2000 ))
INSERT INTO #dir
EXEC master.dbo.xp_cmdshell #cmd;
-- Uncomment the following line, if you want to see what
-- a "dir" looks like from SQL Server !!
-- SELECT * FROM #dir
if EXISTS(SELECT * FROM #dir WHERE [output] LIKE '%' + #filename + '%' )
BEGIN
-- File *was* found in this folder
SET #bFileExists = 1
END
ELSE
BEGIN
-- File was NOT found in this folder
SET #bFileExists = 0
END
SELECT #bFileExists
END
You can call this SP simply by passing it a folder name and a filename:
EXEC [dbo].[DoesFileExist] 'D:\MyFiles', 'SomeExcelFile.xls'
And yes, strangely, it does seem to work, for the SQL Server users who can't use xp_fileexist.
Remember that, to use this code, your SQL Server user must have permissions to use xp_cmdshell :
GRANT EXECUTE ON xp_cmdshell TO YourSQLServerUser

xp_cmdshell Proxy not Executing

I created a Proxy account with Sysadmin access.
Users use this to execute a bcp command of their choosing.
However when the users want's to execute the proc they get: EXECUTE permission was denied on the object 'xp_cmdshell', database 'mssqlsystemresource', schema 'sys'
Here is my Proc:
CREATE PROCEDURE spCMDProxy
(
#SQLSTATEMENT VARCHAR(1000),
#FILENAME VARCHAR(1000)
)
WITH ENCRYPTION
AS
BEGIN
DECLARE #PrepStatement VARCHAR(1000)
SET #PrepStatement = 'bcp ' + '"'+ #SQLSTATEMENT + '" queryout C:\SamsungEDI\' + #FILENAME + ' -U************ -P************ -c -t"||" -S UECZAERP01'
EXEC xp_cmdshell #PrepStatement
END
My Proxy account is a local Sysadmin account.
I found the problem, Could not execute due to the fact that the user cannot execute on xp_cmdshell:
USE master
GRANT EXECUTE on xp_cmdshell to [mydomain\myAccount]
Also found this Article

Resources