A Little More On Powershell Scripting With Racket

Just thought others might find this somewhat interesting:

https://onor.io/2025/01/more-scripting-with-racket.html

3 Likes

This is awesome! Thanks for sharing.

I am currently messing around with some bash for a colleague. I'll have to try PowerShell, soon.

Isn't Racket just delightful?

#! /usr/bin/racket
#lang racket/base

(require
  "help.rkt"
  racket/file
  racket/cmdline)

(define the-site (make-parameter #false))
(define the-host (make-parameter #false))
(define the-fqdn (make-parameter #false))

; PARSE COMMAND-LINE INPUT
(command-line
 #:program "web-vulnerability-scan"
 #:once-each
 [("--site")
  site
  "A url, e.g. https://www.google.com/"
  {the-site site}]
 
 ;; these seem redundant?
 [("--host")
  host
  "A domain and top-level domain, e.g. google.com"
  {the-host host}]

 [("--fqdn")
  fqdn
  "A fully qualified domain name, e.g. www.google.com"
  {the-fqdn fqdn}]
 
 #:args ()
 (unless {the-site} (error 'web-vulnerability-scan "expected a site, found none"))
 (unless {the-host} (error 'web-vulnerability-scan "expected a host, found none"))
 (unless {the-fqdn} (error 'web-vulnerability-scan "expected an FQDN, found none")))

(define (temp-file prefix suffix)
  (path->string (make-temporary-file* prefix suffix)))

;; EXECUTE COMMANDS
(define/command (external-ip)
  #:cmd curl ifconfig.me
  #:res (lambda (ip _) ip))

(define/command (zapit.txt)
  #:pre [(define temp (temp-file #"zapit" #".txt"))]
  ;--------------------------------------------
  #:cmd zaproxy -cmd -zapit ,{the-site} > ,temp
  #:res (lambda _ temp))

(define/command (subdomains.txt)
  #:pre [(define temp (temp-file #"subdomains" #".txt"))]
  ;--------------------------------------
  #:cmd subfinder -d ,{the-host} -o ,temp
  #:res (lambda _ temp))

(define/command (take-overs.txt)
  #:pre [(define temp (temp-file #"take-overs" #".txt"))]
  ;------------------------------------------------
  #:cmd subjack -w ,subdomains.txt -v -ssl -o ,temp
  #:res (lambda _ temp))

...

I was vaguely aware of this fact, but after rediscovering the Scripts chapter in the docs, it has been a breeze.

2 Likes

That's a great use of Racket in a shell script! Kudos!

That's so cool! I've also been trying to use Racket for managing machine learning environments on Linux recently, and I found Racket works really well for this! Here are some code from my project

(Install miniconda and manage virtual env)

#lang racket/base

(require racket/system)

(require "../common-tools/basic-commands.rkt")
(require "../utils.rkt")

(provide conda
         conda-run-in
         conda-create-env
         conda-install-in
         pip-install-in
         env-exist?
         install-miniconda)

(define miniconda-default-installer-url
  "https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh")

(define miniconda-tuna-mirror-install-url
  "https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh")

(define (conda . cmds)
  (system (build-command (cons "conda" cmds))))

(define (conda-run-in env-name cmd)
  (apply conda `("run" "--live-stream" "-n" ,env-name ,cmd)))

(define (conda-create-env env-name . pkgs)
  (apply conda `("create" "-y" "-n" ,env-name ,@pkgs)))

(define (conda-install-in env-name . pkgs)
  (apply conda `("install" "-y" "-n" ,env-name ,@pkgs)))

(define (pip-install-in env-name . pkgs)
  (conda-run-in env-name
                (build-command `("python" "-m" "pip" "install" ,@pkgs))))

(define (env-exist? env-name)
  (conda "list" "--name" env-name))

(define (install-miniconda
         #:install-from [install-from 'default])
  ;; steps from <https://docs.anaconda.com/miniconda/install/#quick-command-line-install>
  (mkdir-p "~/miniconda3")
  (let ([installer-url (cond ['tuna miniconda-tuna-mirror-install-url]
                             [else miniconda-default-installer-url])])
    (wget installer-url "~/miniconda3/" "miniconda.sh"))
  (bash "~/miniconda3/miniconda.sh" "-b" "-u" "-p" "~/miniconda3")
  (rm-rf "~/miniconda3/miniconda.sh")
  (conda "init" "--all"))

(Install JAX)

#lang racket/base

(require "../venv-tools/miniconda.rkt")
(require "../utils.rkt")

(provide create-jax-env
         install-jax-optimize-set-in)

(define (create-jax-env env-name #:gpu [gpu #t])
  (conda-create-env env-name "python=3.11")
  (pip-install-in env-name
                  (if gpu
                      (qotof "jax[cuda12]")
                      "jax")))

(define (install-jax-optimize-set-in env-name)
  (pip-install-in env-name "jaxopt" "optax"))

(Download and compile llama.cpp, a LLM runtime)

#lang racket/base

(require "../common-tools/basic-commands.rkt")
(require "../common-tools/git.rkt")
(require "../compile-tools/cmake.rkt")
(require "../proxy/proxy.rkt")

(define llama-cpp-default-repo "https://github.com/ggerganov/llama.cpp")

(define (download-compile-llama-cpp workdir
                                    #:cuda [cuda #t]
                                    #:clone-with-proxy [clone-with-proxy #f])
  (mkdir-p workdir)
  (apt-get-install "git" "cmake")
  
  (define llama-cpp-dir (build-path workdir "llama-cpp"))
  (if clone-with-proxy
      (with-proxy (git-clone llama-cpp-default-repo llama-cpp-dir))
      (git-clone llama-cpp-default-repo llama-cpp-dir))
  
  (let ([llama-cpp-build-path (build-path llama-cpp-dir "build")])
    (cmake "-B" (path->string llama-cpp-build-path)
           "-S" (path->string llama-cpp-dir)
           (if cuda "-DGGML_CUDA=ON" ""))
    
    (cmake "--build" (path->string llama-cpp-build-path)
           "--config" "Release"
           "-j" "$(nproc)")))
2 Likes

I'll also say that in general shell scripts are a great way to keep a skill sharp. I used practice F# by writing shell scripts for work in it.

No one cares about shell scripts you build for yourself so it's an excellent way to practice a language that's not part of the day job. When people ask me about how they can practice some language beyond C#/Java/JS that's usually my answer--write your shell scripts with it if you can.

2 Likes

Great day to have eyes :eyes:!