1 2 Previous Next 15 Replies Latest reply on May 13, 2014 6:00 PM by wimdecorte

    Server Side Script To Close A DB

    john__j

      Can anyone provide a valid example of a shell script that leverages the "fmsadmin" command to close a database and that can be successfully executed through a server schedule?

       

      The following is the code I'm trying to use to achieve this task:

       

      #!/bin/bash

      #

      sudo fmsadmin close -y mydatabase.fmp12

      exit 0

       

      I've tried running this with the default "fmserver" account and with the server's admin account and both yield unsuccessful results. If I run the scheduled script with the server's admin account I get a Aborted By User error. If I run it with the default fmserver account, the script looks to execute successfully but the database does not actuall close. I've propogated the permissions of Scripts folder down to my custom script and have edited the sudoers file as mentioned in the FileMaker Server documentation.

       

      I'd love to hear the specifics in how some of you are achieving such a task on your server(s).

        • 1. Re: Server Side Script To Close A DB
          wimdecorte

          I don't recall off the top of my head: when you do this in terminal, are you asked for FMS admin credentials?  If so you have to also specify the -u and -p switches and provide the username and pw that can access the admin console.

           

          Also: it is considered best practice to first test for what clients are connected and disconnect them first and trap for errors, especially if the next steps involve trying to move or download the file.

          • 2. Re: Server Side Script To Close A DB
            wimdecorte

            This is a full example on how to do a full automated shutdown on Windows.  The fmsadmin syntax and all of the logic would be the same on OSX.

            The important bits are were the script keeps polling fms to see if clients are connected and if the files were closed properly.

             

            . -----------------------------------------

            ' Author: Wim Decorte

            ' Version: 2.0

            ' Description: Uses the FileMaker Server command line to disconnect

            '               all users And close all hosted files

            '

            ' This is a basic example.  This script is not meant as a finished product,

            ' its only purpose is as a learning & demo tool.

            '

            ' This script does not have full Error handling.

            ' For instance, it will break if there are spaces in the FM file names.

            ' The script also does not handle infinite loops in disconnecting clients

            ' or closing files.

            '

            ' This script is provided as is, without any implied warranty or support.

             

            Const WshFinished = 1

            q = Chr(34)  ' the " character, needed to wrap around paths with spaces

             

             

            '--------------------------------------------------------------------------------------------

            ' Change these variables to match your setup

             

            theAdminUser = ""

            theAdminPW = ""

            pathToSAtool = "C:\Program Files\FileMaker\FileMaker Server\Database Server\fmsadmin.exe"

             

            '--------------------------------------------------------------------------------------------

             

             

            SAT = "cmd /c " & q & pathToSAtool & q & " " ' watch the trailing space

             

            callFMS = SAT

            If Len(theAdminUser) > 0 Then

            callFMS = callFMS & " -u " & theAdminUser

            End If

            If Len(theAdminPW) > 0 Then

            callFMS = callFMS & " -p " & theAdminPW

            End If

             

            listClients = callFMS & " list clients"

            disconnectClients = callFMS & " disconnect client -y"

            listfiles = callFMS & " list files -s"

            closeFiles = callFMS & " close file "

            stopServer = callFMS & " stop server -y -t 15"

             

            ' hook into the Windows shell

            Set sh = WScript.CreateObject("wscript.shell")

             

            ' get a list of all clients and force kick them off

            clientIDs = getCurrentClients()

            clientCount = UBound(clientIDs)

             

            ' loop through the clients and kick them off

            If clientCount > 0 Then

              fullCommand = disconnectClients

              Set oExec = sh.Exec(fullCommand)

              ' give FMS some time and then requery the list of clients

              Do Until oExec.Status = WshFinished

              WScript.Sleep 50

              Loop

                                Do Until clientCount = 0

              WScript.Sleep 1000

              Debug.WriteLine "Waiting for clients to disconnect..."

              clientIDs = getCurrentClients()

              clientCount = UBound(clientIDs)

              Loop

            End If

             

            ' get list of files and close them

            fileIDs = getCurrentFiles()

            fileCount = UBound(fileIDs)

             

            ' loop through the files and close them

            If fileCount > 0 Then

                      Do Until fileCount = 0

              fullCommand = closeFiles & fileIDs(0) & " -y"

              Set oExec = sh.Exec(fullCommand)

              ' give FMS some time and then requery the list of files

              Do Until oExec.Status = WshFinished

              WScript.Sleep 50

              Loop

              fileIDs = getCurrentFiles()

              fileCount = UBound(fileIDs)

             

            Loop

            End If

             

            ' all clients and files stopped

            ' shut down the database sever (does not stop the FMS service!)

            fullCommand = stopServer

            Set oExec = sh.Exec(fullCommand)

            Do Until oExec.Status = WshFinished

            WScript.Sleep 50

            Loop

             

            ' done, exit the script

            Set sh = Nothing

            WScript.Quit

            ' ------------------------------------------------------------------------------

             

            Function getCurrentClients()

             

            tempCount = 0

            Dim tempArray()

            Set oExec = sh.Exec(listClients)

             

            ' in case there are no clients...

            If oexec.StdOut.AtEndOfStream Then Redim temparray(0)

             

            ' read the output of the command

            Do While Not oExec.StdOut.AtEndOfStream

              strText = oExec.StdOut.ReadLine()

              strText = Replace(strtext, vbTab, "")

                                Do Until InStr(strtext, "  ") = 0

              strText = Replace (strtext, "  ", " ")

              Loop

              If InStr(strText, "Client ID User Name Computer Name Ext Privilege") > 0 OR _

                                          InStr(strText, "ommiORB") > 0 OR _

              InStr(strText, "IP Address Is invalid Or inaccessible") > 0 Then

              ' do nothing

              Redim temparray(0)

              Else

              tempClient = Split(strtext, " ")

              tempCount = tempCount + 1

              Redim Preserve tempArray(tempCount)

              tempArray(tempCount-1) = tempClient(0)

              End If

            Loop

             

            getCurrentClients = tempArray

             

            End Function

             

            Function getCurrentFiles()

             

            tempCount = 0

            Dim tempArray()

            Set oExec = sh.Exec(listfiles)

             

            ' in case there are no files...

            If oexec.StdOut.AtEndOfStream Then Redim temparray(0)

             

            ' read the output of the command

            Do While Not oExec.StdOut.AtEndOfStream

              strText = oExec.StdOut.ReadLine()

              strText = Replace(strtext, vbTab, "")

                                Do Until InStr(strtext, "  ") = 0

              strText = Replace (strtext, "  ", " ")

              Loop

              If InStr(strText, "ID File Clients Size Status Enabled Extended Privileges") > 0 OR _

                                          InStr(strText, "ommiORB") > 0 OR _

              InStr(strText, "IP Address Is invalid Or inaccessible") > 0 OR _

                                          Left(strtext, 2) = "ID" Then

              ' do nothing

              Redim temparray(0)

              Else

              tempFile = Split(strtext, " ")

              status = LCase(tempFile(4))

                                          If status = "normal" Then

              tempCount = tempCount + 1

              Redim Preserve tempArray(tempCount)

              tempArray(tempCount - 1) = tempFile(1) & ".fp7"

              End If

              End If

            Loop

             

            getCurrentFiles = tempArray

             

            End Function

            • 3. Re: Server Side Script To Close A DB
              john__j

              When you run the command in Terminal you are prompted for the fmserver account password. I actually run the command without the sudo in Terminal when achieving this task manually. In doing this you have to hit return to accept the defualt admin account as the account to run the command under then type in it's password.

               

              The frustrating part is that in FileMaker Server 13 you have the ability to run a schedule under the default account (Mac = fmserver) or by specifying a different account. But when leveraging both these options I can't get the script to work. Depeding on which account I run the script under and whether or not the "sudo" portion is present (or the "exit 0") it either looks like it runs successfully but nothing actually happens or I get an error in the form of either Aborted By User or a scripting error...

               

              Thank you for your example code, unfortunately it's not much use to me. All of our FileMaker clients and servers are Mac.

               

              Also, I'm trying to achieve this task without having to code the username and password into the script. I thought FileMaker Server's ability to execute a schedule under either the default account or other specified account would achieve this...?

              • 4. Re: Server Side Script To Close A DB
                wimdecorte

                john__j wrote:

                 

                 

                Thank you for your example code, unfortunately it's not much use to me. All of our FileMaker clients and servers are Mac.

                 

                The core (where it uses the fmsadmin command line and the logic structure is going to be the same, so it is easy to port to a shell script

                 

                 

                john__j wrote:

                 

                 

                Also, I'm trying to achieve this task without having to code the username and password into the script. I thought FileMaker Server's ability to execute a schedule under either the default account or other specified account would achieve this...?

                 

                Nope, two different things.  Interaction with the fmsadmin CLI requires the account that was set up to administer FMS, the same account you use to open the admin console itself.

                 

                It would be a bit of a security risk if anyone could make FMS execute things under the default fmserver account (that gets installed with FMS).

                • 5. Re: Server Side Script To Close A DB
                  john__j

                  wimdecorte wrote:

                   

                  Nope, two different things.  Interaction with the fmsadmin CLI requires the account that was set up to administer FMS, the same account you use to open the admin console itself.

                   

                  In this case, the account that I'm specifying in the CLI is the same account that is set up to administer FMS.

                   

                  Let's take another angle at this dilemma. I will describe how I can successfully execute the command in the CLI then explain how I execute the command through a server side scheduled script. Then maybe it will be more clear as to why it's not working from FMS or what I might be missing.

                   

                       (in Terminal)

                       1) type: sudo fmsadmin close -y mydatabasename.fmp12

                       2) hit return to execute the command with the account setup to administer FMS

                       3) type: the password for that account

                       4) SUCCESS: database closes as expected

                   

                       (in FMS)

                       1) create a shell script with the following code:    

                       #!/bin/bash

                       #

                       sudo fmsadmin close -y mydatabase.fmp12

                       exit 0

                       2) place that shell script in FMSs default Scripts folder

                       3) propogate permissions of that folder down to the newly created shell script file

                       4) creat a schedule in FMS that uses the shell script file

                       5) specify the FMS enabled account and password (same on as in step 2 above) to execute the schedule

                       6) run the schedule

                       7) NO SUCCESS: schedule runs successfully but did not work, the database is still open! The following is information captured in the log just after running the schedule:

                      
                  Why don't I get the same result?
                  Disclaimer: I know this script is very raw, I'm just trying to get something working at the moment. Once I can prove the mechanism I will then be interested in refining it further.
                  • 6. Re: Server Side Script To Close A DB
                    john__j

                    john__j wrote:

                     

                         7) NO SUCCESS: schedule runs successfully but did not work, the database is still open! The following is information captured in the log just after running the schedule:

                    Server Log output:

                     

                    May 8, 2014 12:35:16 PM                    Server Events          Information          150          Schedule “TEST2_ServerSideScript” completed

                    May 8, 2014 12:35:15 PM                    Server Events          Information          731          Schedule “TEST2_ServerSideScript” has started system script “untitled2.sh” with process ID 70053

                    • 7. Re: Server Side Script To Close A DB
                      wimdecorte

                      john__j wrote:

                       

                       

                           (in Terminal)

                           1) type: sudo fmsadmin close -y mydatabasename.fmp12

                           2) hit return to execute the command with the account setup to administer FMS

                           3) type: the password for that account

                           4) SUCCESS: database closes as expected

                       

                       

                      The thing that you need to get past is that the fmsadmin CLI does NOT inherit privileges from the running account.   You MUST specify an admin account with the command.  Just like what happens when you do it from Terminal as you mention above.

                       

                      Hardcoding credentials in a shell script is not ideal and I don't like it either but that's the way it is.  There are obviously ways to not hard-code the credentials but have the script read them from an secure location etc.  But it does drive up the complexity of the script.

                      • 8. Re: Server Side Script To Close A DB
                        user19752

                        sudo itself needs password as you type at 3) on terminal.

                        It is same when runs in shell script.

                        There are some ways to resolve it, see 'man sudo' on terminal for detail.

                        One may be run the script as root, but I think it is not good way...

                        • 9. Re: Server Side Script To Close A DB
                          john__j

                          wimdecorte wrote:

                           

                          The thing that you need to get past is that the fmsadmin CLI does NOT inherit privileges from the running account.   You MUST specify an admin account with the command.  Just like what happens when you do it from Terminal as you mention above.

                           

                          I understand that you have to specify an admin account with the command. I've demonstrated this be pionting out how I run my command via Terminal and via FMS by using said admin credentials. And, as I pointed out with the log example, I can get the script to run successfully via an FMS scheduled server side script BUT it actually doesn't execute the same (or at all) through FMS as it does in Terminal.

                          • 10. Re: Server Side Script To Close A DB
                            wimdecorte

                            john__j wrote:

                             

                            as I pointed out with the log example, I can get the script to run successfully via an FMS scheduled server side script BUT it actually doesn't execute the same (or at all) through FMS as it does in Terminal.

                             

                            The log simply reports that the SCHEDULE was run, but it does not give you any feedback about what the schedule did.  That's up to you to provide exit statuses that will be reflected in the log.

                            • 11. Re: Server Side Script To Close A DB
                              user19752

                              Hmm, /usr/bin/fmsadmin is installed as everyone can execute it, so sudo is needless.

                              On terminal, fmsadmin command requires "username and password" (when option is not supplied), not only password.

                              If you don't see username prompt, removing 'sudo' will require nothing to input, then success.

                               

                              I may have misread that 2) saying about username prompt...

                              • 12. Re: Server Side Script To Close A DB
                                john__j

                                I believe you did misread the Terminal Step #2 listed above. In any event, the real question at hand isn't dealing with executing the command in Terminal. Rather, it's about getting the command to run through a FMS scheduled script without having to code the username and password in the script...

                                • 13. Re: Server Side Script To Close A DB
                                  user19752

                                  So, write the password to a 'protected' text file and use it in script as

                                  fmsadmin -u username -p `cat /path/to/the/protected/file` close -y mydatabase.fmp12

                                  This should work but I can't mean difference from protecting the script file itself, since the password file should be accessible by the account to run the script.


                                  • 14. Re: Server Side Script To Close A DB
                                    sibrcode

                                    Hi Wim,

                                     

                                    Is it still necessary to be so careful when closing a file? My impression is that now (but perhaps not circa FMS 9) using the -t option is sufficient to have users disconnected and the file gracefully closed. The same goes when using the fmsadmin stop server command.

                                     

                                    Admittedly, haven't tested this out.

                                    1 2 Previous Next