ProgrammingPro #81: Debugging Linux Scripts, Tabnine's Code Review Agent, and Zed Editor's SSH Remoting
Welcome to this week’s edition of ProgrammingPro!
In today’s Expert Insight, we bring you an excerpt from the recently published book, The Ultimate Linux Shell Scripting Guide, which explains how to use -u and set -u in shell scripts to identify uninitialized variables and prevent related errors during debugging.
News Highlights: Zed editor adds SSH remoting for faster remote workflows; IBM’s AI agents automate GitHub issue resolution; Java’s JEP 491 boosts concurrency with virtual thread improvements; and Tabnine’s Code Review Agent enforces custom coding standards.
My top 5 picks from today’s learning resources:
But there’s more, so dive right in.
Stay Awesome!
Divya Anne Selvaraj
Editor-in-Chief
🗞️News and Analysis🔎
Rust-based Zed editor preview adds direct SSH remoting, a key feature for potential VS Code switchers: Zed emphasizes speed, performance, and real-time collaboration, appealing to developers seeking a faster, lighter alternative.
Tabnine’s new Code Review Agent validates code based on a dev team’s unique best practices and standards: The agent is an AI tool that validates code, flags issues during code reviews, and offers fixes.
IBM releases open AI agents for resolving GitHub issues: IBM’s SWE-Agent 1.0, a set of AI-powered open agents, automates GitHub issue resolution, helping developers by localizing, suggesting fixes, and executing tests.
Java Evolves to Tackle Virtual Threads Pinning with JEP 491: The change would improve scalability and performance in highly concurrent applications by allowing threads to unmount from platform threads during synchronization.
Apache Tomcat 11.0 Delivers Support for Virtual Threads and Jakarta EE 11: The update enhances concurrency, scalability, and security for modern web applications, with upgrades in WebSocket and Servlet performance.
Microsoft Introduces Modern Web App Pattern for .NET: Accelerating App Modernization to the Cloud: The pattern guides developers in transforming monolithic applications to cloud-native architectures with a focus on scalability.
Amazon Q Developer is not just for coding and not just for AWS, claims cloud giant: It includes features like multi-file edits, unit testing, and security scanning, and plans to add support for Eclipse IDE.
🎓Tutorials and Learning Resources💡
Python
Hidden Python Libraries That Will Blow Your Mind: Introduces six powerful yet lesser-known Python libraries including Streamlit for quick app-building, PyWhatKit for task automation, and Typer for simplified CLIs.
For more Python resources, go to PythonPro
C# and .NET
🎓Tutorial | Unlocking the Power of GitHub Models in .NET with Semantic Kernel: Explains how to set up necessary packages, configure access with GitHub tokens, establish a Semantic Kernel client, and run a chat-based application.
🎓Tutorial | eShop infused with AI – a comprehensive intelligent app sample: Demonstrates how to integrate AI functionalities like semantic search, summarization, classification, and sentiment analysis into business applications.
🎓Tutorial | How to prevent XSS Attacks in ASP.NET Core Web API: Covers essential practices such as input validation, output encoding, and advanced measures like Content Security Policy (CSP) and secure cookies.
C and C++
🎓Tutorial | Deep Threads Diving Into The Core Of Concurrent Programming With C: Covers core concepts like threads vs. processes, key functions in POSIX threads (pthreads), and synchronization techniques.
📖Open Access Book | Is Parallel Programming Hard, And, If So, What Can You Do About It?: Serves as a guide for programming shared-memory parallel systems, offering foundational techniques to prevent common pitfalls.
C++, Complexity, and Compiler Bugs: Explores challenges such as temporary lifetime extension, differences in designated initializers between C++ and C, and inconsistent handling of template disambiguation across compilers.
Java
Java-Based No-Code and Low-Code Application Bootstrapping Tools: Reviews four Java-based no-code and low-code platforms: Appsmith, Wavemaker, Openkoda, and JHipster.
🎓Tutorial | Building thread-safe abstractions in Java versus Go: Through examples, the author compares Java's
synchronizedkeyword for mutual exclusion with Go’ssync.Mutexand channels, showcasing adaptations needed.🎓Tutorial | Server-Side Rendering with Spring Boot: Explains how to use WebJars for managing client-side dependencies via Maven and Thymeleaf for server-side rendering in Spring Boot.
JavaScript and TypeScript
🎓Tutorial | The magic of keeping one level of abstraction per function: Advocates for breaking down complex tasks into focused, smaller functions, to achieve cleaner code that is easier to update, reuse, and understand.
Summary of the AJAX frameworks comparison: Compares Vue.js, Alpine.js, HTMX, and Vaadin—across frontend skills required, team integration, setup ease, and styling flexibility.
20 TypeScript Tips for Cleaner, More Efficient Code in 2024: Tips include NonNullable, Partial, Readonly, Mapped Types, Union Exhaustiveness, and Generics, with practical examples demonstrating each.
Go
🎓Tutorial | Writing secure Go code: Covers tools like
go vet,staticcheck,golangci-lint,govulncheck, andgosecwhich support code analysis and vulnerability detection, and fuzz testing which helps find security flaws.🎓Tutorial | Ranging over functions in Go 1.23: Introduces Go 1.23’s new feature allowing for-range iteration over functions, enhancing custom container iteration without exposing internal data structures.
Rust
Rust's Most Subtle Syntax: Explores how Rust’s pattern-matching rules with constants can introduce subtle bugs, especially if naming conventions aren’t followed consistently.
Bringing faster exceptions to Rust: Explores speeding up Rust’s panic handling by optimizing the unwinding mechanism, resulting in a 4.3x speed improvement without changing the Rust compiler or system unwinder.
Swift
🎓Tutorial | swift-format GitHub Action: Covers setting up swift-format as a GitHub Action to automate linting and formatting for Swift projects, including configuration tips and integration with Xcode 16.
🎓Tutorial | How to Use URLSession with Async/Await for Network Requests in Swift: Covers GET and POST methods, adding parameters, and decoding JSON responses into Swift structs.
PHP
🎥🎓Tutorial | Laravel for Beginners: This video series offers a step-by-step introduction to Laravel, covering essentials like setting up, routing, views, Blade directives, layouts, components, and CSS integration with Tailwind.
SQL
🎓Tutorial | Advanced SQL for Data Professionals: Covers common table expressions (CTEs) for recursive queries, methods to remove duplicates, ways to identify new records, strategies for filling gaps in data, and more.
Ruby
🎓Tutorial | Understanding Ruby 3.3 Concurrency: A Comprehensive Guide: Covers Threads, Fibers, and Ractors, explaining each's distinct use cases, performance trade-offs, and resource utilization.
Kotlin
🎓Tutorial | Serializing SQL: Building Serializable Data Classes in Kotlin: Describes building a system in Kotlin to serialize SQL queries into data classes using JSON, enabling dynamic SQL functions like SUM, and COUNT.
🌟Best Practices and Advice🚀
Cell-Based Architecture Adoption Guidelines: Outlines guidelines for adopting cell-based architecture, a strategy that enhances system resilience by isolating failures, ideal for high-availability systems.
Being a Responsible Developer in the Age of AI Hype: Discusses recognizing that AI models like LLMs generate plausible text rather than true reasoning, questioning claims of AI’s capabilities, and addressing biases and ethical risks.
A deep look into our new massive multitenant architecture: Explores the the architectural overhaul undertaken by Glauber Costa's team at Turso, focusing on adopting Deterministic Simulation Testing (DST).
Using certifications to level up your development career: Explains how obtaining relevant, vendor-neutral certifications can boost developers' careers by validating their skills, improving job prospects, and potentially increasing pay.
🧠Expert Insight📚
Here’s an excerpt from “Chapter 21: Debugging Shell Scripts" in the book, The Ultimate Linux Shell Scripting Guide by Donald A. Tevault, published in October 2024.
Checking for Undefined Variables
As I said at the beginning of this chapter, in the Understanding Common Scripting Errors section, it’s sometimes desirable to define a variable in a script without assigning an initial value to it. But, sometimes it isn’t. You can track down uninitialized variables by appending a -u to the end of your shebang line.
In bash for example, you can use #!/bin/bash -u , which will turn this feature on for the entire script. Or, you can place a set -u command any place in the script where you’d like to start checking. For example, let’s look at the unassigned_var1.sh script, which has variable checking turned off:
#!/bin/bash
echo "The uninitialized myvar, without setting -u, looks like this : " $myvar
echo
myvar=Donnie
echo "I've just initialized myvar."
echo "The value of myvar is: " $myvar
Here’s the output:
donnie@fedora:~$ ./unassigned_var1.sh
The uninitialized myvar, without setting -u, looks like this :
I've just initialized myvar.
The value of myvar is: Donnie
donnie@fedora:~$
As you see, without the -u setting, the script runs to completion. It’s just that trying to echo the value of the uninitialized myvar just shows us a blank space. Next, let’s turn on variable checking by adding the -u option, as you see in the unassigned_var2.sh script:
#!/bin/bash -u
echo "The uninitialized myvar, without setting -u, looks like this : " $myvar
echo
myvar=Donnie
echo "I've just initialized myvar."
echo "The value of myvar is: " $myvar
Let’s see what this does:
donnie@fedora:~$ ./unassigned_var2.sh
./unassigned_var2.sh: line 2: myvar: unbound variable
donnie@fedora:~$
This time the script failed as soon as it saw the uninitialized variable.
You can set the -u option anywhere in the script you like, by using set -u , as you see here in the unassigned_var3.sh script:
#!/bin/bash
echo "The uninitialized myvar, without setting -u, looks like this : " $myvar
echo
echo "I'm now setting -u."
set -u
myvar=Donnie
echo "I've just initialized myvar."
echo "The value of myvar is: " $myvar
echo
echo "Let's now try another uninitialized variable."
echo "Here's the uninitialized " $myvar2
So now, I have one uninitialized variable at the top, on line 2. (Let’s just say that for whatever reason, I want this particular variable to be uninitialized.) I then turn on variable checking on line 5. Let’s see how this runs:
donnie@fedora:~$ ./unassigned_var3.sh
The uninitialized myvar, without setting -u, looks like this :
I'm now setting -u.
I've just initialized myvar.
The value of myvar is: Donnie
Let's now try another uninitialized variable.
./unassigned_var3.sh: line 11: myvar2: unbound variable
donnie@fedora:~$
Before I turn on variable checking, the uninitialized myvar just shows us a blank space. After I turn on variable checking, I initialized myvar with a value of Donnie , and it prints out normally. But, the uninitialized myvar2 at the end crashes the script.
NOTE:
If you search the web for shell scripting security tutorials, you’ll find several that tell you to make either -u or set -u a permanent part of your scripts. The authors of these tutorials say that it enhances the security of your scripts, without giving any convincing explanation of why or how. Using -u or set -u is great for debugging, but it should only be used for just that—debugging! So, when you’re through debugging your scripts, be sure to remove the -u or the set -u before you place the script into production. Otherwise, your scripts could give you some rather unpredictable results.
Also, be aware that using -u can also help you detect typos in your scripts. For example, if you define a variable as mynum=1 , but accidentally call back the value with $mymum , the -u will detect that mymum is an unset variable.
The Ultimate Linux Shell Scripting Guide was published in October 2024. Packt library subscribers can continue reading the entire book for free or you can buy the book here!
Get the eBook for $43.99 $29.99
🛠️Useful Tools⚒️
PipelineDP4j: Google’s open-source JVM library for differential privacy in Java, Kotlin, and Scala, supporting Apache Beam.
Whirlwind: A high-performance, asynchronous sharded HashMap in Rust for thread-safe, concurrent data access.
Modus: An open-source, serverless framework for fast APIs and AI functions using WebAssembly, with support for AssemblyScript and Go.
That’s all for today.
We have an entire range of newsletters with focused content for tech pros. Subscribe to the ones you find the most useful here.
If your company is interested in reaching an audience of developers, software engineers, and tech decision makers, you may want to advertise with us.




