--- name: srand signature: 'srand EXPR' since: 5.0 status: documented categories: ["Numeric functions"] --- ```{index} single: srand; Perl built-in ``` *[Numeric functions](../perlfunc-by-category)* # srand Seed the pseudo-random number generator. `srand` sets the internal state of the PRNG that [`rand`](rand) draws from. Call it with an explicit integer to get a reproducible stream, or call it with no argument to reseed from the best entropy source the platform offers. Since Perl 5.14 `srand` **returns the seed it used**, so you can log it and replay the same run later. ## Synopsis ```perl srand EXPR srand ``` ## What you get back The seed that was installed, as an integer. For `srand($n)` the return value is `$n` (after the usual integer truncation). For argument-less `srand()` the return value is the auto-chosen seed drawn from system entropy — capture it if you ever want to reproduce the run. ```perl my $seed = srand(); # auto-seed, remember what we used warn "seed for this run: $seed\n"; ``` Before Perl 5.14 `srand` returned nothing useful. Code that relies on the seed return should declare the minimum version: ```perl use v5.14; # so srand returns the seed ``` ## Global state `srand` mutates a single process-wide PRNG. Every subsequent call to [`rand`](rand) in the same process — from any package, any module, any thread-free context — reads from that one state. There is no per-package or per-scope RNG. Consequences: - Calling `srand($k)` anywhere in the program affects *every* later [`rand`](rand) call, including those inside modules you did not write. - Two processes that call `srand($k)` with the same `$k` produce identical [`rand`](rand) streams. This is the basis of reproducible tests and the reason you must reseed after [`fork`](fork). - If `srand` is never called explicitly, it is called implicitly **without argument** the first time [`rand`](rand) is invoked. ## Examples Reproducible test case with an explicit seed — same input, same sequence, every run: ```perl srand(42); my @sample = map { rand() } 1..5; # identical on every invocation ``` Seed from `time()` for rare-collision randomness across separate runs started at different wall-clock seconds. This is the classical pattern; it is **not** cryptographic-grade: ```perl srand(time() ^ $$); # time XOR pid, old-school spread ``` Save-seed, restore-seed pattern for a test that picks a random subset of its cases but logs enough to replay any failure: ```perl my $seed = srand(); # auto-seed, capture it eval { run_randomised_tests() }; if ($@) { warn "FAILED with seed=$seed — reproduce with: srand($seed)\n"; die $@; } ``` Reseed after [`fork`](fork) so parent and child do not share a stream: ```perl my $pid = fork(); die "fork: $!" unless defined $pid; if ($pid == 0) { srand(); # child gets fresh entropy exec_child_work(); } ``` Two independent streams from the same seed — useful when you want to checkpoint and resume, or diff two runs that diverged after a decision point: ```perl srand(12345); my @first = map { rand() } 1..10; srand(12345); my @second = map { rand() } 1..10; # identical to @first ``` ## Edge cases - **No-argument form auto-seeds with the best available entropy.** On Linux this draws from `/dev/urandom` (or `getrandom(2)`). The seed is wide enough that you should treat it as opaque, not as a small integer. - **Do not call `srand()` without arguments more than once per process.** The PRNG's internal state already carries more entropy than any single seed can restore, so re-seeding *loses* randomness rather than adding it. The two legitimate reasons to call it repeatedly are (a) with an explicit seed for reproducibility, and (b) once in each child after [`fork`](fork). - **Decimal arguments are silently truncated to integer.** `srand(42)` and `srand(42.9)` install the same seed. Always pass an integer so intent is obvious. - **Same seed ⇒ identical [`rand`](rand) stream.** That is the whole point for tests; it is the whole problem for security. - **Not cryptographically secure.** [`rand`](rand)/`srand` use a fast non-cryptographic PRNG. Do not use them to generate session tokens, nonces, keys, password salts, or anything an adversary must not be able to predict. Use [`Crypt::URandom`][cu] or read from `/dev/urandom` directly. - **`PERL_RAND_SEED` environment variable.** If set to a non-negative integer at process startup, argument-less `srand()` (including the implicit call triggered by the first [`rand`](rand)) installs a deterministic seed derived from that value. The derivation is deliberately unspecified; only same-value-same-binary-same-code reproducibility is guaranteed. Intended for debugging and performance analysis. The variable is read **once** at startup; mutating `%ENV` later has no effect on the current process. - **Threads** (`use threads`): each interpreter clone gets its own PRNG state. Seeding in one thread does not affect another. - **Scope of the seed**: there is no way to [`local`](local)-ise the PRNG state. If a library you call in between does an `srand`, your stream is perturbed. Capture and restore manually if that matters. ## Differences from upstream Fully compatible with upstream Perl 5.42. `PERL_RAND_SEED` is honoured with the same "deliberately unspecified but reproducible" contract as perl5. ## See also - [`rand`](rand) — the consumer of the state `srand` installs; draws the next value from the seeded stream - [`time`](time) — seconds since the epoch; the classic quick-and-dirty seed source for non-security code (`srand(time() ^ $$)`) - [`Crypt::URandom`][cu] — cryptographically secure random bytes from the OS entropy pool; use this, not [`rand`](rand), for tokens and keys - [`Math::Random::MT`][mt] — Mersenne Twister PRNG with its own independent state, when you need a second stream that is not perturbed by library calls to [`rand`](rand) - `perlrun` — documents the `PERL_RAND_SEED` environment variable and other startup knobs [cu]: https://metacpan.org/pod/Crypt::URandom [mt]: https://metacpan.org/pod/Math::Random::MT