This New Years Day, Learn The Jot Command The jot command is one I haven’t used in awhile. But it’s still useful. Let’s take a look at a few of the things you can do with it. First, let’s just print lines into a new file called “century.txt” which we can do by running with the number of increments followed by the starting number, and then redirecting the output into the file name:
jot 100 1 > ~/Desktop/century.txt
Or to do integers instead, simply put the decimals:
jot 100 1.00 > ~/Desktop/century.txt
Or in descending order,
jot – 100 1 > ~/Desktop/century.txt
Now we could change the output to be just 50 to 100, by incrementing 50 (the first position) and starting at 50 (the second):
jot 50 50
The jot command is able to print sequential data, as we’ve seen. But we can also print random data, using the -r option. Following that option we have three important positions, the first is the number of iterations, but the next two are the lower and upper boundaries for the numbers, respectively. So in the below command we’ll grab 10 iterations (or ten random numbers) that are between 1 and 1000:
jot -r 10 1 1000
Now if we were to add a -c in there and use a and z as the upper and lower bounds, we’d get… letters (this time we’re just gonna’ ask for one letter)!
jot -r -c 1 a z
Something I find useful is just to shove random data into a file infinitely. And by useful I mean hopefully not left running overnight on my own computer (been there, done that). To do this, just use a 0 for the number of iterations:
jot -r -c 0
Something that is actually useful is the basic ASCII set:
jot -c 128 0
We can also append data to a word using -w. So let’s say we want to print the characters aa followed by a through z. In the below we’ll define that with -w and then we’ll list those two characters followed by %c which is where the character substitution goes and then the number of iterations followed by the lower bound:
jot -w aa%c 26 a
You can also do stuttering sequences, useful for the occasional tango dancer, so here we’ll do a 5/3 countdown:
jot – 100 0 -.5
Or we could create a one meg file by creating 1,024 bytes:
jot -b 0 1024 > onemegfile.txt
Oh wait, that file’s two megs. Get it? 😉
And running strings teaches you that you can’t bound random (a good lesson for the New Year). Anything you use jot for?
Happy New Years!
There are a lot of scripts stored on github. And you can run them directly by curling them into bash. To do so, you’ll need a link to the raw script (using the github page with the URL of the script brings in all the cruft, so you’ll need to find the raw text). To grab that, click on the page with the script and then right-click on Raw, as seen here: Then, throw out a bash command followed by < and then the URL you just copied into your clipboard in parenthesis:
bash <(curl -Ls https://github.com/krypted/resetsoftwareupdate/raw/master/resetsoftwareupdate.sh)
The caffeinate command is pretty cool. It keeps your computer from going to sleep. It can run in a couple of different ways. There’s a timer that prevents sleep for a little while. You can also run another command from within caffeinate that keeps the system awake until the other command is finished. Here, we’ll scp a file called source file to a host called servername and keep the system from going to sleep until the process is finished:
caffeinate -s scp sourcefile me:servername/targetfileHere, we’ll just use the boring command to tell the computer not to go to sleep for an hour:
caffeinate -t 3600 &
Web Services in Mac OS X, Mac OS X Server, Linux and most versions of Unix are provided by Apache, an Open Source project that much of the Internet owes its origins to. Apache owes its name to the fact that it’s “a patchy” service. These patches are often mods, or modules. Configuring web services is as easy in OS X Mavericks Server (10.9) as it has ever been. To set up the default web portal, simply open the Server app, click on the Websites service and click on the ON button. After a time, the service will start. Once running, click on the View Server Website link at the bottom of the pane. Provided the stock OS X Server page loads, you are ready to use OS X Server as a web server. Before we setup custom sites, there are a few things you should know. The first is, the server is no longer really designed to remove the default website. So if you remove the site, your server will exhibit inconsistent behavior. Also, don’t remove the files that comprise the default site. Instead just add sites, which is covered next. Webmail is gone. You don’t have to spend a ton of time looking for it as it isn’t there. Also, Mountain Lion Server added web apps, which we’ll briefly review later in this article as well, as those continue in Mavericks Server and subsequently in Yosemite Server. Finally, enabling PHP and Python on sites is done globally, so this setting applies to all sites hosted on the server. Now that we’ve got that out of the way, let’s add our first custom site. Do so by clicking on the plus sign. At the New Web Site pane, you’ll be prompted for a number of options. The most important is the name of the site, with other options including the following:
- Domain Name: The name the site is accessible from. The default sites do not have this option as they are accessible from all names that resolve to the server.
- IP Address: The IP address the site listens on. Any means the site is available from every IP address the server is configured to use. The default websites do not have this option as they are accessible from all addresses automatically
- Port: By default, sites without SSL run on port 80 on all network interfaces, and sites with SSL run on port 443 on all network interfaces. Use the Port field to use custom ports (e.g., 8080). The default sites do not have this option as they are configured to use 80 and 443 for default and SSL-based communications respectively.
- SSL Certificate: Loads a list of SSL certificates installed using Keychain or the SSL Certificate option in the Settings pane of the Server application
- Store Site Files In: The directory that the files that comprise the website are stored in. These can be placed into the correct directory using file shares or copying using the Finder. Click on the drop-down menu and then select Other to browse to the directory files are stored in.
- Who Can Access: By default Anyone (all users, including unauthenticated guests) can access the contents of sites. Clicking on Anyone and then Customize… brings up the “Restrict access to the following folders to a chosen group” screen, where you can choose web directories and then define groups of users who can access the contents.
- Additional Domains: Click on the Edit… button to bring up a simple list of domain names the the site also responds for (e.g. in addition to krypted.com, add www.krypted.com).
- Redirects: Click on the Edit… button to bring up a list of redirects within the site. This allows configuring redirects to other sites. For example, use /en to load english.krypted.com or /cn to load china.krypted.com).
- Aliases: Click on the Edit… button to load a list of aliases. This allows configuring redirects to folders within the same server. For example, /en loads /Library/Server/Web/Data/Sites/Default
- Index Files: Click on the Edit… button to bring up a list of pages that are loaded when a page isn’t directly indicated. For example, when visiting krypted.com, load the wp.php page by default.
- Advanced Options: The remaining options are available by clicking on the “Edit Advanced Settings…” button.
- Enable Server Side Includes: Allows administrators to configure leveraging includes in web files, so that pieces of code can be used across multiple pages in sites.
- Allow overrides using .htaccess files: Using a .htaccess file allows administrators to define who is able to access a given directory, defining custom user names and passwords in the hidden .htaccess file. These aren’t usually required in an OS X Server web environment as local and directory-based accounts can be used for such operations. This setting enables using custom .htaccess files instead of relying on Apple’s stock web permissions.
- Allow folder listing: Enables folder listings on directories of a site that don’t have an Index File (described in the non-Advanced settings earlier).
- Allow CGI execution: Enables CGI scripts for the domain being configured.
- Use custom error page: Allows administrators to define custom error pages, such as those annoying 404 error pages that load when a page can’t be found
- Make these web apps available on this website: A somewhat advanced setting, loads items into the webapps array, which can be viewed using the following command: sudo serveradmin settings web:definedWebApps
sudo serveradmin start webTo stop the service(s):
sudo serveradmin stop webAnd to see the status:
sudo serveradmin fullstatus webFullstatus returns the following information:
web:health = _empty_dictionary web:readWriteSettingsVersion = 1 web:apacheVersion = "2.2" web:servicePortsRestrictionInfo = _empty_array web:startedTime = "2013-10-08 01:05:32 +0000" web:apacheState = "RUNNING" web:statusMessage = "" web:ApacheMode = 2 web:servicePortsAreRestricted = "NO" web:state = "RUNNING" web:setStateVersion = 1While the health option typically resembles kiosk computers in the Computer Science departments of most major universities, much of the rest of the output can be pretty helpful including the Apache version, whether the service is running, any restrictions on ports and the date/time stamp that the service was started. To see all of the settings available to the serveradmin command, run it, followed by settings and then web, to indicate the Websites service:
sudo serveradmin settings webThe output is pretty verbose and can be considered in two sections, the first includes global settings across sites as well as the information for the default sites that should not be deleted:
web:defaultSite:documentRoot = "/Library/Server/Web/Data/Sites/Default" web:defaultSite:serverName = "" web:defaultSite:realms = _empty_dictionary web:defaultSite:redirects = _empty_array web:defaultSite:enableServerSideIncludes = no web:defaultSite:customLogPath = ""/var/log/apache2/access_log"" web:defaultSite:webApps = _empty_array web:defaultSite:sslCertificateIdentifier = "" web:defaultSite:fullSiteRedirectToOtherSite = "" web:defaultSite:allowFolderListing = no web:defaultSite:serverAliases = _empty_array web:defaultSite:errorLogPath = ""/var/log/apache2/error_log"" web:defaultSite:fileName = "/Library/Server/Web/Config/apache2/sites/0000_any_80_.conf" web:defaultSite:aliases = _empty_array web:defaultSite:directoryIndexes:_array_index:0 = "index.html" web:defaultSite:directoryIndexes:_array_index:1 = "index.php" web:defaultSite:directoryIndexes:_array_index:2 = "/wiki/" web:defaultSite:directoryIndexes:_array_index:3 = "default.html" web:defaultSite:allowAllOverrides = no web:defaultSite:identifier = "37502141" web:defaultSite:port = 80 web:defaultSite:allowCGIExecution = no web:defaultSite:serverAddress = "*" web:defaultSite:requiresSSL = no web:defaultSite:proxies = _empty_dictionary web:defaultSite:errorDocuments = _empty_dictionary web:defaultSecureSite:documentRoot = "/Library/Server/Web/Data/Sites/Default" web:defaultSecureSite:serverName = "" web:defaultSecureSite:realms = _empty_dictionary web:defaultSecureSite:redirects = _empty_array web:defaultSecureSite:enableServerSideIncludes = no web:defaultSecureSite:customLogPath = ""/var/log/apache2/access_log"" web:defaultSecureSite:webApps = _empty_array web:defaultSecureSite:sslCertificateIdentifier = "com.apple.systemdefault.9912650B09DE94ED160146A3996A45EB3E39275B" web:defaultSecureSite:fullSiteRedirectToOtherSite = "" web:defaultSecureSite:allowFolderListing = no web:defaultSecureSite:serverAliases = _empty_array web:defaultSecureSite:errorLogPath = ""/var/log/apache2/error_log"" web:defaultSecureSite:fileName = "/Library/Server/Web/Config/apache2/sites/0000_any_443_.conf" web:defaultSecureSite:aliases = _empty_array web:defaultSecureSite:directoryIndexes:_array_index:0 = "index.html" web:defaultSecureSite:directoryIndexes:_array_index:1 = "index.php" web:defaultSecureSite:directoryIndexes:_array_index:2 = "/wiki/" web:defaultSecureSite:directoryIndexes:_array_index:3 = "default.html" web:defaultSecureSite:allowAllOverrides = no web:defaultSecureSite:identifier = "37502140" web:defaultSecureSite:port = 443 web:defaultSecureSite:allowCGIExecution = no web:defaultSecureSite:serverAddress = "*" web:defaultSecureSite:requiresSSL = yes web:defaultSecureSite:proxies = _empty_dictionary web:defaultSecureSite:errorDocuments = _empty_dictionary web:dataLocation = "/Library/Server/Web/Data" web:mainHost:keepAliveTimeout = 15.000000 web:mainHost:maxClients = "50%"The second section is per-site settings, with an array entry for each site:
web:customSites:_array_index:0:documentRoot = "/Library/Server/Web/Data/Sites/www2.krypted.com" web:customSites:_array_index:0:serverName = "www2.krypted.com" web:customSites:_array_index:0:realms = _empty_dictionary web:customSites:_array_index:0:redirects = _empty_array web:customSites:_array_index:0:enableServerSideIncludes = no web:customSites:_array_index:0:customLogPath = "/var/log/apache2/access_log" web:customSites:_array_index:0:webApps = _empty_array web:customSites:_array_index:0:sslCertificateIdentifier = "" web:customSites:_array_index:0:fullSiteRedirectToOtherSite = "" web:customSites:_array_index:0:allowFolderListing = no web:customSites:_array_index:0:serverAliases = _empty_array web:customSites:_array_index:0:errorLogPath = "/var/log/apache2/error_log" web:customSites:_array_index:0:fileName = "/Library/Server/Web/Config/apache2/sites/0000_any_80_www2.krypted.com.conf" web:customSites:_array_index:0:aliases = _empty_array web:customSites:_array_index:0:directoryIndexes:_array_index:0 = "index.html" web:customSites:_array_index:0:directoryIndexes:_array_index:1 = "index.php" web:customSites:_array_index:0:directoryIndexes:_array_index:2 = "/wiki/" web:customSites:_array_index:0:directoryIndexes:_array_index:3 = "default.html" web:customSites:_array_index:0:allowAllOverrides = no web:customSites:_array_index:0:identifier = "41179886" web:customSites:_array_index:0:port = 80 web:customSites:_array_index:0:allowCGIExecution = no web:customSites:_array_index:0:serverAddress = "*" web:customSites:_array_index:0:requiresSSL = no web:customSites:_array_index:0:proxies = _empty_dictionary web:customSites:_array_index:0:errorDocuments = _empty_dictionaryThe final section (the largest by far) includes array entries for each defined web app. The following shows the entry for a Hello World Python app:
web:definedWebApps:_array_index:20:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:20:includeFiles = _empty_array web:definedWebApps:_array_index:20:requiredModuleNames = _empty_array web:definedWebApps:_array_index:20:startCommand = "" web:definedWebApps:_array_index:20:sslPolicy = 0 web:definedWebApps:_array_index:20:requiresSSL = no web:definedWebApps:_array_index:20:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:20:launchKeys:_array_index:0 = "org.postgresql.postgres" web:definedWebApps:_array_index:20:proxies = _empty_dictionary web:definedWebApps:_array_index:20:preflightCommand = "" web:definedWebApps:_array_index:20:stopCommand = "" web:definedWebApps:_array_index:20:name = "org.postgresql.postgres" web:definedWebApps:_array_index:20:displayName = ""Each site has its own configuration file defined in the array for each section. By default these are stored in the /Library/Server/Web/Config/apache2/sites directory, with /Library/Server/Web/Config/apache2/sites/0000_any_80_www2.krypted.com.conf being the file for the custom site we created previously. As you can see, many of the options available in the Server app are also available in these files:
ServerName www2.krypted.com ServerAdmin firstname.lastname@example.org DocumentRoot "/Library/Server/Web/Data/Sites/www2.krypted.com" DirectoryIndex index.html index.php /wiki/ default.html CustomLog /var/log/apache2/access_log combinedvhost ErrorLog /var/log/apache2/error_log SSLEngine Off SSLCipherSuite “ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM” SSLProtocol -ALL +SSLv3 +TLSv1 SSLProxyEngine On SSLProxyProtocol -ALL +SSLv3 +TLSv1Options All -Indexes -ExecCGI -Includes +MultiViews AllowOverride None DAV Off Deny from all ErrorDocument 403 /customerror/websitesoff403.html The serveradmin command can also be used to run commands. For example, to reset the service to factory defaults, delete the configuration files for each site and then run the following command:
sudo serveradmin command web:command=restoreFactorySettingsThe final tip I’m going to give in this article is when to make changes with each app. I strongly recommend making all of your changes in the Server app when possible. When it isn’t, use serveradmin and when you can’t make changes in serveradmin, only then alter the configuration files that come with the operating system by default. I also recommend keeping backups of all configuration files that are altered and a log of what was altered in each, in order to help piece the server back together should it become unconfigured miraculously when a softwareupdate -all is run next.
A really neat new feature in 2012R2 is that Hyper-V can resize a running virtual machine (.vhdx) to the smallest possible size, while the virtual machine is running. To do so, use Get-VM in PowerShell. Here, we’ll use the -Path option to define the location of our vhdx, the -ToMinimumSize option to indicate that we’d like to shrink it down as low as we can go and -AsJob so it runs in the background:
Resize-VHD –Path D:\myVM.vhdx –ToMinimumSize -AsJob
Since the early days, OS X Server has supported performing the serveradmin commands through a web interface. This interface was accessible at the address of the server followed by a colon and then 311 in a web browser. This feature was disabled by default in Mountain Lion. But fear causes hesitation, and hesitation will cause your worst fears to come true, so we’re going to turn it back on here in Server 3. To enable, use the following command:
sudo defaults write /Library/Preferences/com.apple.servermgrd requireUserAgent -bool falseOnce done, open https://127.0.0.1:311 in a web browser, or replace 127.0.0.1 with the address of the server if accessing from another location. This is stimulating, but we’re out of here. So, authenticate to be greeted with a list of services. At the Server Admin Modules page, each service output from `serveradmin list` appears. Clicking each produces the ability to run the commands you can supply using `serveradmin command` along with the service name. For example, to get a list of all of the connected AFP users in OS X Mountain Lion Server, run the following command:
sudo serveradmin command afp:command = getConnectedUsersNow, to get the same list, click on the servermgr_afp.html link and then click on getConnectedUsers. You then see an XML output that shows who’s connected (since I’m on a flight right now, luckily no one is connected to mine). Now you also have a URL in the toolbar, which should look something like this:
https://127.0.0.1:311/commands/servermgr_afp?input=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%0D%0A%3Cplist+version%3D%220.9%22%3E%0D%0A%3Cdict%3E%0D%0A%09%3Ckey%3Ecommand%3C%2Fkey%3E%0D%0A%09%3Cstring%3EgetConnectedUsers%3C%2Fstring%3E%0D%0A%3C%2Fdict%3E%0D%0A%3C%2Fplist%3E%0D%0A&send=Send+CommandRad, unicode. I guess spaces aren’t really compliant in URLs. Before we look at that, let’s take a look at what we can do with these. If you follow what I write, you have probably noticed that I use curl for tinkering with URLs a lot. In many cases, this is not the right tool. But I usually start there and move on if need be. Six seconds. We’re going to be meat waffles. Because we’re going to assume the server is using a self-signed cert that we don’t yet trust, we’re gonna’ use a -k along with curl. Then we’re going to follow that with the link. However, since we need to auth, we’re going to also go ahead and embed the username (in this case johhny) followed by a : and then the password (in this example, bodhi), followed by an @ in between the https:// and the server address, as follows:
curl -k https://johhny:email@example.com:311/commands/servermgr_afp?input=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%0D%0A%3Cplist+version%3D%220.9%22%3E%0D%0A%3Cdict%3E%0D%0A%09%3Ckey%3Ecommand%3C%2Fkey%3E%0D%0A%09%3Cstring%3EgetConnectedUsers%3C%2Fstring%3E%0D%0A%3C%2Fdict%3E%0D%0A%3C%2Fplist%3E%0D%0A&send=Send+CommandThe output includes the afp:usersArray which shows active connections. The most interesting options, other than those for services you run in your environment, ar those under servermgr_info. Here, you can get PIDs for processes, kill PIDs, view logs, check file sizes, delete data and even reboot servers. Overall, this option has some security concerns, but provides some good insight into how the Server Admin tool worked under the hood in Mac OS X Lion Server and below while also serving as a functional option as an API for the product, especially given that output is in XML, similar to the output of most other modern APIs.
You can delete an IP address from the arp table using the arp command along with the -d option followed by an address. For example, to delete IP 10.10.10.1:
arp -d 10.10.10.1If you’re not sure which IP address you’re looking for then you can look at the arp table to check the IP against the MAC address by using the -a option along with arp. For example:
arp -aTo delete all of the entries in an arp table (they do regenerate after all) you can use the -d option in conjunction with the -a option:
arp -d -aIf you then want to manually add an entry into the arp table you can use the -s option followed first by the IP address and then by the MAC address, as follows (assuming an IP of 10.10.10.10 and a MAC of 00-00-00-00-00-00):
arp -s 10.10.10.10 00-00-00-00-00-00In some cases I’ve had to revert to using hostnames instead of MAC addresses. To do so, first define the hostname in /etc/hosts, adding a line that has the IP followed by the name of the server, as follows:
havok.krypted.com 10.10.10.10Then simply use the name instead of the MAC address with the -s option, as follows:
arp -s havok.krypted.com 10.10.10.10
The exit command will close an MS-DOS prompt. It’s quick, dirty and easy to use. Exit.