{"id":13673,"date":"2010-06-17T07:00:00","date_gmt":"2010-06-17T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2010\/06\/17\/as-random-as-i-wanna-be-why-cmd-exes-random-isnt-so-random\/"},"modified":"2010-06-17T07:00:00","modified_gmt":"2010-06-17T07:00:00","slug":"as-random-as-i-wanna-be-why-cmd-exes-random-isnt-so-random","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20100617-00\/?p=13673","title":{"rendered":"As random as I wanna be: Why cmd.exe&#039;s %RANDOM% isn&#039;t so random"},"content":{"rendered":"<p>\nSomebody on my team reported that\na particular script in our project&#8217;s build process\nwould fail with bizarre output maybe\nonce in fifty tries.\nThis script was run from a <code>makefile<\/code>,\nand the result was a failed build.\nRerunning <i>make<\/i> fixed the problem,\nbut that&#8217;s not much consolation when the build lab encounters it\napproximately every other day.\nThe strange thing about the bizarre output was that it appeared\nto contain a mix of two different runs.\nHow could the output of two runs be mixed into one output file?\n<\/p>\n<p>\nThe script was a batch file, and it generated its output in\na few different steps,\nstoring the intermediate output in randomly-named temporary files,\ntaking advantage of the\n<a HREF=\"http:\/\/technet.microsoft.com\/en-us\/library\/bb490954.aspx\">\n<code>%RANDOM%<\/code><\/a>\npseudovariable to generate the name of those temporary files.\n(They were <code>%TEMP%\\%RANDOM%.tmp1<\/code>,\n<code>%TEMP%\\%RANDOM%.tmp2<\/code>, you get the idea.)\n<\/p>\n<p>\nCutting to the chase: The reason for the mixed output was that\nthe <code>%RANDOM%<\/code> pseudo-variable wasn&#8217;t random enough.\nIf two copies of the script are running at the same time,\nthey will get the <i>same<\/i> &#8220;random&#8221; number and end up\nmixing their output together.\n(And running multiple builds at the same time is something the\npeople in the build lab are wont to do.)\n<\/p>\n<p>\nIt turns out that the Windows command processor uses\n<a HREF=\"http:\/\/taeb-nethack.blogspot.com\/2009\/03\/predicting-and-controlling-nethacks.html\">\nthe standard na&iuml;ve algorithm for seeding the random number generator<\/a>:\n<\/p>\n<pre>\n   srand((unsigned)time(NULL));\n<\/pre>\n<p>\nSince <code>time<\/code> has a resolution of one second,\ntwo command prompts launched in rapid succession have a good\nchance of seeding the random number generator with the same\ntimestamp, which means that they will have the same random number\nstream.\n<\/p>\n<pre>\nC&gt; copy con notsorandom.cmd\n@pause\n@echo %RANDOM%\n^Z\n        1 file(s) copied.\nC&gt; for \/l %i in (1,1,3000) do @cmd \/c notsorandom.cmd\n\/\/ hold down the space bar\nPress any key to continue . . .\n14153\nPress any key to continue . . .\n14153\nPress any key to continue . . .\n14153\nPress any key to continue . . .\n14153\nPress any key to continue . . .\n14156\nPress any key to continue . . .\n14156\nPress any key to continue . . .\n14156\nPress any key to continue . . .\n14156\nPress any key to continue . . .\n14156\nPress any key to continue . . .\n14160\nPress any key to continue . . .\n14160\nPress any key to continue . . .\n14160\n<\/pre>\n<p>\nNotice that the <code>%RANDOM%<\/code> pseudovariable generates\nthe same &#8220;random&#8221; number until the clock ticks over another second.\n(Notice also that the &#8220;random&#8221; numbers don&#8217;t look all that random.)\n<\/p>\n<p>\nWe fixed the script so it generated its temporary file in the\nproject&#8217;s output directory rather than in the (shared) <code>%TEMP%<\/code>\ndirectory.\nThat way, even if two copies of the project are building at the same\ntime, they will generate their temporary files in different directories\nand not step on each other.\n<\/p>\n<p>\n<b>Exercise<\/b>: There is much subtlety in that <code>for<\/code>\ncommand.\nDescribe alternative formulations of the <code>for<\/code> command,\nboth those that work and those that don&#8217;t.\nTo get you started: Explain the output of this variation:\n<\/p>\n<pre>\n<code>for \/l %i in (1,1,300) do @(pause&amp;echo %RANDOM%)<\/code>\n<\/pre>\n<p>\n<b>Obligatory batch file bashing<\/b>:\nEvery time I write an entry about batch files,\nyou can count on people complaining about how insane\nthe batch programming language is.\nThe batch language wasn&#8217;t designed; it evolved.\n(And according to commenter Daev,\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2008\/08\/06\/8835317.aspx#8841279\">\nit followed a form of parallel evolution<\/a> from what most people\nare familiar with.)\nI doubt anybody actually enjoy writing batch files.\nAt best you tolerate it.\nI&#8217;m just trying to make it slightly more tolerable.\nI bet these are the same people who complain to their tax preparer\nabout the complexity of tax law.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Somebody on my team reported that a particular script in our project&#8217;s build process would fail with bizarre output maybe once in fifty tries. This script was run from a makefile, and the result was a failed build. Rerunning make fixed the problem, but that&#8217;s not much consolation when the build lab encounters it approximately [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[104],"class_list":["post-13673","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-tipssupport"],"acf":[],"blog_post_summary":"<p>Somebody on my team reported that a particular script in our project&#8217;s build process would fail with bizarre output maybe once in fifty tries. This script was run from a makefile, and the result was a failed build. Rerunning make fixed the problem, but that&#8217;s not much consolation when the build lab encounters it approximately [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/13673","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=13673"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/13673\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=13673"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=13673"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=13673"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}